Javascript-如果在定义函数时创建了函数的词法环境,那么为什么在函数之后可以声明一个自由变量?
作者:互联网
编辑:感谢您的答案,我想我现在明白了.它需要了解范围和吊装.以下是一个我认为很好地说明了这两个示例的新示例:
var a = function (){
alert(x);
}
var x = 1;
(function(){
var x = 2;
a();
})();
上面的警报1.警报作用范围由该警报1而不是2来说明,而起吊作用则由以下事实说明:“ var x = 1”行位于a的声明和带有$的匿名函数的定义之后“警报(x)”.据称,吊装意味着以上等同于以下(来源:http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html):
var x;
var a = function (){
alert(x);
}
x = 1;
(function(){
var x = 2;
a();
})();
因此,由于x是在函数定义之前有效地初始化的,因此“ alert(x)”中的x与随后设置为1的x是相同的.
由于JS使用词法作用域,因此“ var x = 2”行不会覆盖与a关联的x.
那是对的吗?
-原始问题-
我花了整整一天的时间试图弄清楚这一点.我已经阅读了一些有关Java语言中的作用域和闭包的文章,但这仍然使我难以理解.
有人告诉我,函数的词法环境是在定义函数时创建的,而不是在执行时创建的.
因此,如果在程序的任何地方都没有声明名为x的变量,那么当我这样做时指向的匿名函数的关闭环境是什么?
var a = func(){
var y = 7; //just for illustrative purposes
alert(x);
});
我的理解是环境是变量名到值的映射…所以
y: 7
x: ?
那是对的吗?以下代码警告“ 10”:
(function (){
var a = function(){
alert(x);
};
var x = 10;
a();
})();
我的猜测是,当调用a时,JS检查关闭环境中是否有x的映射,但没有找到映射,随后检查了本地环境,并找到了由“ var x = 10”设置为10的x.那正确吗?
如果是这种情况,那么我希望以下内容也能起作用,但事实并非如此:
var a = function(){
alert(x);
};
(function (){
var x = 10;
a();
})();
我希望发生的是,当执行a时,出现“ alert(x);”.运行时,它检查x的关闭环境,没有发现,然后检查“ var x = 10”所在的外部环境并找到x.但是相反,我得到一个未定义x的错误.
最初定义a的匿名函数时,如果我能知道解释器完成的“准备”工作可能会有所帮助-当解释器在“ alert(x)”中遇到x时.
谢谢
解决方法:
将闭包视为堆栈.每个函数在该堆栈中都有一个map / hash.这是一个示例,其中每个级别都有一个x的值,该值被子闭合覆盖.
function a(){
var x = 2;
function b(){
var x = 3;
function c(){
var x = 4;
}
}
}
当引用x的值时,js处理器查找当前的闭包.查找未定义,它将遍历闭包堆栈以尝试查找值.只有达到最高级别或“全局”范围时,它才会放弃并给出“未定义”的值.
您的示例在这里:
var a = function(){
alert(x); //no value of x in this closure
};
//no value of x in this closure either
(function (){
var x = 10; //this is a completely separate stack
a(); //no value of 'a' in this closure, but there is one in global scope
})();
我可以在不知道匿名函数中的“ x”的情况下看到对“ a”函数的困惑.关闭范围是按“书面”定义的,而不是“按要求的”定义.您不能从该闭包范围之外插入或混淆函数闭包范围中的变量.这是关于js的事情之一,这让我发疯,我希望与众不同.我真希望有一组关键字可以解决闭包范围…
标签:scope,closures,javascript 来源: https://codeday.me/bug/20191121/2055276.html