函数与作用域
2017-08-12 本文已影响0人
Jeff12138
函数声明和函数表达式有什么区别
- 函数声明的本质是使用
function
声明一个函数,而函数表达式的本质是将一个函数赋值给一个变量; - 函数声明不必放在函数调用之前,而函数表达式必须放在调用函数之前。
什么是变量的声明前置?什么是函数的声明前置
在一个作用域下,所有的var
声明变量的语句在被解析时都会被前置,例如:
console.log(a);
var a = 3;
console.log(a);
上述语句在解析时会自动将var a
这条声明语句前置,再执行:
console.log(a);
a = 3;
console.log(a);
同理,function
声明的函数也会被前置,例如:
sayHello();
function sayHello(){
console.log('hello');
}
也会将声明语句前置,再执行sayHello();
。
这也解释了为什么函数声明不必放在函数调用之前。
arguments 是什么
在函数内部,我们可以使用arguments[i]
来获取函数中相对应的某个参数。
这样做可以简化函数语句,避免定义一些不必要的参数,但会令函数的可读性变差。
函数的"重载"怎样实现
由于JS属于弱类型语言,所以它不能像某些强类型语言一样实现重载,在JS中同名函数会进行覆盖。
要实现类似重载的功能,我们可以通过检查传入参数的类型和数量,来执行相应的逻辑语句。
立即执行函数表达式是什么?有什么作用
(function(){
var a = 1;
})()
类似上述语句。我们将一个匿名函数用小括号括起,并在末尾加一对小括号,这样的函数在被读取到时会立即被调用和执行。这样的写法相当于将声明函数和调用函数合并。
它的主要作用在于隔离作用域,避免污染全局变量。
求n!,用递归来实现
function factor(n){
if(n<0){
return'对不起,负数没有阶乘!'
}
if(n===0){
return 1;
}
else{
return n*factor(n-1)
}
}
以下代码输出什么?
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(){
var sum = 0;
for(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); //undefined
var a = 1;
console.log(b); //报错
变量a的声明会前置,但赋值不会。所以console.log(a);
相当于只声明了变量却没有赋值,所以输出undefined;
变量b既没有声明也没有赋值,所以console.log(b);
报错。
如下代码的输出?为什么
sayName('world');
sayAge(10);
function sayName(name){
console.log('hello ', name);
}
var sayAge = function(age){
console.log(age);
};
输出“hello world”和报错。
因为function sayName(name)
是一个函数声明,它可以放在调用函数之后,而不影响函数的执行;而var sayAge = function(age)
则是一个函数表达式,只有其中的var sayAge
前置了,所以sayAge
是一个变量而不是函数,因此sayAge(10);
会报错。
如下代码输出什么? 写出作用域链查找过程伪代码
var x = 10
bar()
function foo() {
console.log(x)
}
function bar(){
var x = 30
foo()
}
//最终输出为:10
/*
1.
globalContext = {
AO: {
x: 10
foo: function
bar: function
},
Scope: null
}
//声明 foo 时 得到下面
foo.[[scope]] = globalContext.AO
//声明 bar 时 得到下面
bar.[[scope]] = globalContext.AO
2.
barContext = {
AO: {
x: 30
},
Scope: bar.[[scope]] //globalContext.AO
}
3.
fooContext = {
AO: {},
Scope: foo.[[scope]] // globalContext.AO
}
*/
如下代码输出什么? 写出作用域链查找过程伪代码
var x = 10;
bar()
function bar(){
var x = 30;
function foo(){
console.log(x)
}
foo();
}
//最终输出为:30
/*
1.
globalContext = {
AO: {
x: 10
bar: function
},
Scope: null
}
//声明 bar 时 得到下面
bar.[[scope]] = globalContext.AO
2.
barContext = {
AO: {
x: 30,
foo: function
},
Scope: bar.[[scope]] //globalContext.AO
}
//在 bar 的执行上下文里声明 foo 时 得到下面
foo.[[scope]] = barContext.AO
3.
fooContext = {
AO: {},
Scope: foo.[[scope]] // barContext.AO
}
*/
以下代码输出什么? 写出作用域链的查找过程伪代码
var x = 10;
bar()
function bar(){
var x = 30;
(function (){
console.log(x)
})()
}
//最终输出为:30
/*
1.
globalContext = {
AO: {
x: 10
bar: function
},
Scope: null
}
//声明 bar 时 得到下面
bar.[[scope]] = globalContext.AO
2.
barContext = {
AO: {
x: 30,
function
},
Scope: bar.[[scope]] //globalContext.AO
}
//在 bar 的执行上下文里声明 function 时 得到下面
function.[[scope]] = barContext.AO
3.
functionContext = {
AO: {},
Scope: function.[[scope]] // barContext.AO
}
*/
以下代码输出什么? 写出作用域链查找过程伪代码
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
fn: function
fn3: function
},
Scope: null
}
fn.[[scope]] = globalContext.AO
fn3.[[scope]] = globalContext.AO
2.
fnContext = {
AO: {
a: undefined,
fn2: function,
};
Scope: fn.[[scope]] //globalContext.AO
}
fn2.[[scope]] = fnContext.AO
3.
fn3Context = {
AO:{
a: 200,
},
Scope:fn3.[[scope]]//globalContext.AO
}
4.
fn2ConText = {
AO:{
a: 20,
},
Scope:fn2.[[scope]]//fnContext.AO
}
开始执行代码
-var a = 1; //声明全局变量a = 1,即globalContext中a = 1;
-function fn() //调用函数fn();
-console.log(a) //var a声明前置但未赋值,所以输出undefined;
-var a = 5; //赋值a = 5,即fnContext中a = 5;
-console.log(a) //输出5;
-a++ //a值自增变为6,即fnContext中a变为6;
-fn3 //调用函数fn3();
-console.log(a) //在globalContext中a = 1,所以输出1;
-a = 200 //globalContext中a值变为200;
-fn2() //调用函数fn2();
-console.log(a) //在fnContext中a = 6,所以输出6;
-a=20 //fnContext中a值变为20;
-console.log(a) //在fnContext中a = 20,所以输出20;
-console.log(a) ///globalContext中a = 200,所以输出200。
因此,最终输出结果为:undefined 5 1 6 20 200
*/