javascript作用域道理进修
在每次挪用一个函数的时候,就会进入一个函数内的作用域,当从函数返回
今后,就会返回挪用前的作用域。
ECMA262关于作用域完成的形貌:
任何实行上下文时候的作用域,都是由作用域链(scope chain)来完成的。
在一个函数被定义的时候,会将它此时的作用域链链接到这个函数对象的[[scope]]属性。
在一个函数被挪用时,会建立一个运动对象,然后关于函数的每个形参,都定名为该运动对象的定名属性,然后将这个运动对象做为此时的作用域链最前端,并将这个函数的[[scope]]属性加入到作用域链中。
用例子申明。来自鸟哥的博客;
function factory() {
var name = 'Elric';
var intro = function(){
alert('I am ' + name);
}
return intro;
}
function app(para){
var name = para;
var func = factory();
func();
}
app('eva');
我是这么明白的:
由于
JavaScript中的函数运行在它们被定义的作用域里,而不是它们被实行的作用域里.
所以,intro的作用域链应该是 intro –> factory –> window
当挪用进入到intro时,对name的查找不会进入app的作用域,所以输出的值是Elric
再来一个例子。来自阮一峰先生的微博;
function a(x, y) {
y = function(){
x = 2;
};
return function() {
var x = 3;
y();
console.log(x);
}.apply(this, arguments);
}
a();// 3
我是这么明白的:
根据定义来,return的匿名函数的作用域链应该是[[scope]] –> a –>window
所以,在挪用的时候,它最先找到的是本身的x的值,而实行y,修正的是a中的x的值。
如果把代码改成:
function a(x, y) {
var x = 1;
y = function() {
x = 2;
};
return function() {
y();
console.log(x);
}.apply(this, arguments);
}
a();// 2
这里输出的原本应该是1,然则!然则实行了y,y把a中的x修正成2.由于y的作用域链是y –>a –>window;
然后,在segmentfault上看到的
function a(x, y) {
var name = 1;
y = function() {
x = 2;
};
return function() {
var name = 3;
y();
console.log(this.x);
}.apply(this, arguments);
}
a();// undefined
我简朴的明白为,这里的this.x相当于window.x。所以是undefined。
总结:
JavaScript中的函数运行在它们被定义的作用域里,而不是它们被实行的作用域里.
从定义出发去剖析函数的作用域,而不是经由过程挪用的递次。
参考资料
1.鸟哥:Javascript作用域道理
2.明白 JavaScript 作用域和作用域链
3.阮一峰先生微博上的关于js作用域的一道题