函数与作用域
函数声明和函数表达式有什么区别
- 函数声明使用function关键字可以声明一个函数(声明不必放到调用的前面)
//函数声明
function sayHello(){
console.log('hello')
}
//函数调用
sayHello()
- 函数表达式(声明必须放到调用的前面)
var sayHello = function(){
console.log('hello');
}
sayHello()
两者最大的区别是:函数表达式(function expression)非常类似于函数声明(function statement)(详情查看函数声明),并且拥有几乎相同的语法。函数表达式与函数声明的最主要区别是函数名称(function name),在函数表达式中可忽略它,从而创建匿名函数(anonymous functions)。一个函数表达式可以被用作一个IIFE(即时调用的函数表达式),它一旦定义就运行
参考
什么是变量的声明前置?什么是函数的声明前置
- 变量的声明前置:JavaScript引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,然后给他初始值undefined,然后才逐句执行程序,这就叫做“变量提升”,也即“变量的声明前置”
- 函数的声明前置:函数的声明前置就是把整个函数提升到当前作用域的最前面(位于前置的变量声明后面)
arguments 是什么
- 在函数内部,你可以使用arguments对象获取到该函数的所有传入参数
function printPersonInfo(name, age, sex){
console.log(name);
console.log(age);
console.log(sex);
console.log(arguments);
}
函数的"重载"怎样实现
- 在 JS 中没有重载! 同名函数会覆盖。 但可以在函数体针对不同的参数调用执行相应的逻辑
function printPeopleInfo(name, age, sex){
if(name){
console.log(name);
}
if(age){
console.log(age);
}
if(sex){
console.log(sex);
}
}
printPeopleInfo('Byron', 26);
printPeopleInfo('Byron', 26, 'male');
立即执行函数表达式是什么?有什么作用
(function(){
var a = 1;
})()
console.log(a); //undefined
( function (){
var a = 1;
} () )
console.log(a);
- 作用:
- 不必为函数命名,避免了污染全局变量
- 隔离作用域,封装一些外部无法读取的私有变量
求n!,用递归来实现
function factor(n){
if(n < 0){
break;
}
else if ( n == 0 || n==1 ){
return 1;
}else {
return n * factor(n-1)
}
}
factor(n)
以下代码输出什么?
function getInfo(name, age, sex){
console.log('name:',name);
console.log('age:', age);
console.log('sex:', sex);
console.log(arguments);
arguments[0] = 'valley';
console.log('name', name);
}
getInfo('饥人谷', 2, '男'); //输出为"name:饥人谷 age:2 sex:男" "饥人谷 2 男" "name valley"
getInfo('小谷', 3); //输出为"name:饥人谷 age:3 sex:undefined" "饥人谷 3" "name valley"
getInfo('男'); //输出为"name:饥人谷 age:undefined sex:undefined " "饥人谷" "name valley"
写一个函数,返回参数的平方和?
function sumOfSquares(){
for(var i=0;i<arguments.length;i++){
sum=sum+arguments[i]*arguments[i]
}
return sum;
}
var result = sumOfSquares(2,3,4)
var result2 = sumOfSquares(1,3)
console.log(result) //29
console.log(result2) //10
如下代码的输出?为什么
console.log(a);
var a = 1;
console.log(b); // 输出为"undefined"; 报错;因为a有声明但是在console.log之前无值,b则既无声明也无值所以会报错
如下代码的输出?为什么
sayName('world');
sayAge(10);
function sayName(name){
console.log('hello ', name);
}
var sayAge = function(age){
console.log(age);
}; //输出为''hello world",因为sayName函数声明前置之后,参数为World所以输出为''hello world";之后会报错,因为var sayAge = function(age){console.log(age);}为函数表达式所以必须放在调用函数之前
如下代码输出什么? 写出作用域链查找过程伪代码
var x = 10
bar()
function foo() {
console.log(x)
}
function bar(){
var x = 30
foo()
}
/*
1.进入全局作用域
globalContext= {
AO:{
x: 10;
foo: function
bar: function
},
Scope:null
}
//声明 foo 时 得到下面
foo.[[scope]] = globalContext.AO
//声明 bar 时 得到下面
bar.[[scope]] = globalContext.AO
2.进入bar作用域
barContext = {
AO:{
x:30
},
Scope: bar.[[scope]] //globalContext.AO
}
3.进入foo作用域
fooContext = {
AO:{},
foo.[[scope]] = globalContext.AO
}
*/
输出结果为"10"
如下代码输出什么? 写出作用域链查找过程伪代码
var x = 10;
bar()
function bar(){
var x = 30;
function foo(){
console.log(x)
}
foo();
}
/*
1.进入全局作用域
globalContext = {
AO:{
X:10
bar: function
},
Scope:null
}
//声明 bar 时 得到下面
bar.[[scope]] = globalContext.AO
2.进入bar作用域
barContext = {
AO:{
X:30
foo:function
},
Scope:bar.[[scope]] = globalContext.AO
}
3.进入foo作用域
fooContext = {
AO:{}
Scope:foo.[[scope]] = barContext.AO
},
//声明 foo时 得到下面
foo.[[scope]] = barContext.AO
*/
所以输出为"30"
以下代码输出什么? 写出作用域链的查找过程伪代码
var x = 10;
bar()
function bar(){
var x = 30;
(function (){
console.log(x)
})()
}
/*
1.进入全局作用域
globalContext = {
AO:{
X:10
bar:function
},
Scope:null
}
//声明 bar时 得到下面
bar.[[scope]] = globalContext.AO
2.进入bar作用域
barContext = {
AO:{
X:30
function: function
},
Scope:bar.[[scope]] = globalContext.AO
}
//声明 function时 得到下面
function.[[scope]] = barContext.AO
3.进入function作用域
functionContext = {
AO:{},
}
Scope:function.[[scope]] = barContext.AO
*/
所以输出为"30"
以下代码输出什么? 写出作用域链查找过程伪代码
var a = 1;
function fn(){
console.log(a)
var a = 5
console.log(a)
a++
var a
fn3()
fn2()
console.log(a)
function fn2(){
console.log(a)
a = 20
}
}
function fn3(){
console.log(a)
a = 200
}
fn()
console.log(a)
/*
1.进入全局作用域
globalContext = {
AO:{
a:1/200 //a值的变化
fn:function
fn3:function
}
Scope:null
}
//声明 fn时 得到下面
fn.[[scope]] = globalContext.AO
//声明 fn时 得到下面
fn3.[[scope]] = globalContext.AO
2.进入fn作用域
fnContext = {
AO:{
a:undefined/5/6/20 //a值的变化
fn2:function
}
Scope:fn.[[scope]] = globalContext.AO
}
//声明 fn2时 得到下面
fn2.[[scope]] = fnContext.AO
3.进入fn3作用域
fn3Context = {
AO:{},
Scope:fn3.[[scope]] = globalContext.AO
}
4.进入fn2作用域
fn2Context = {
AO:{},
Scope:fn2.[[scope]] = fnContext.AO
}
4.进入fn3作用域
fn3Context = {
AO:{
a:200
}
Scope:Scope:fn3.[[scope]] = globalContext.AO
}
所以输出结果为(undefined 5 1 6 20 200)
*/