函数参数的词法环境是什么?

时间:2017-05-31 22:56:28

标签: javascript

Javascript支持First Class Functions,在这种情况下,我们可以将函数作为参数传递。在另一个函数的参数列表中定义的匿名函数,该匿名函数的词法环境(即范围)是什么?

例如:

var m = 2;

(function(p1,p2){
   p2(p1);
})(true, function(p1){  // an anonymous function passed as an argument.
   m = 3;
   if(p1){...}
}); // the end of self-invoked function expression.

3 个答案:

答案 0 :(得分:2)

该函数可以访问定义它的范围,并包括任何父范围(例如全局/窗口)。如果在另一个函数内部定义,它将可以访问该函数中定义的任何变量。如果像回调一样作为参数传入,它将无法访问传递给它的函数中定义的变量,因为它是在该函数之外定义的并作为参数传入。

示例:

var a = 1;

(function(callback){ //func1
    //access variable in parent scope
    console.log('func1', a); //outputs 1

    //define a new variable within this function's scope
    var b = 2;

    //call our callback
    callback();

    //define and call a function within this function's scope
    (function(){ //func3
        //access variable in parent scope
        console.log('func3', a); //outputs 1
        //access variable in parent function scope
        console.log('func3', b); //outputs 2
    })();

})(function(){ //func2
    //access variable in parent scope
    console.log('func2', a); //outputs 1
    //access variable from invoking function
    console.log('func2', b); //outputs undefined
});

这会输出类似:

func1 1
func2 1
func2 undefined
func3 1
func3 2

其中所有函数都可以看到变量a,因为它位于所有函数的父作用域中。参数函数无法看到变量b,因为b在另一个函数中定义,参数函数在外部定义并作为参数传入。第一个函数中定义的函数可以同时看到ab

答案 1 :(得分:1)

调用IIFE实际上与首先将函数分配给变量,然后通过该变量调用函数相同;与任何其他匿名函数的使用一样,它只是一个避免给函数命名的快捷方式。所以:

(function(p1,p2){
   p2(p1);
})(true, function(p1){  // an anonymous function passed as an argument.
   m = 3;
   if(p1){...}
});

相当于:

var temp = function(p1,p2){
   p2(p1);
};
temp(true, function(p1) {
   m = 3;
   if(p1){...}
});

除了向外部范围添加temp之外;由于此变量不会出现在其他任何地方,因此无效。所有其他变量的范围在两种情况下是相同的。

答案 2 :(得分:1)

如果您不确定调用的参数列表中定义的函数范围是什么,请注意

fn(function x(…) { … })

相当于

_temp = function x(…) { … };
fn(_temp)

在实际调用之前评估参数,并且在与评估调用本身相同的范围内对它们进行评估。