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作用域的一道题
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。