作用域链
- VO中包含一个额外的属性,该属性指向创建该VO的函数本身
- 每个函数在创建时,会有一个隐藏属性
[[scope]],它指向创建该函数时的AO - 当访问一个变量时,会先查找自身VO中是否存在,如果不存在,则依次查找
[[scope]]属性。
某些浏览器会优化作用域链,函数的[[scope]]中仅保留需要用到的数据。
js
var g = 0;
function A() {
var a = 1;
function B() {
var b = 2;
var C = function() {
var c = 3;
console.log(c, b, a, g);
}
C();
}
B();
}
A();
闭包
js
var a = 1;
function A() {
console.log(a);
}
function Special() {
var a = 5;
var B = A;
B();
}
Special();此处,B是一个闭包,函数A定义的时候的词法环境是a=1。
闭包记录的是函数定义时候的环境,而不是执行时候的环境。
面试题
如果一眼能看出来的,就无需复杂分析。如果一眼看不出来就是要绕的题,那么就画出执行栈去分析。
js
var foo = { n: 1 };
(function (foo) {
console.log(foo.n); // 1
foo.n = 3;
var foo = { n: 2 };
console.log(foo.n); // 2
})(foo);
console.log(foo.n); // 3js
var food = "rice";
var eat = function () {
console.log(`eat ${food}`);
};
(function () {
var food = "noodle";
eat();//eat rice
})();js
var food = "rice";
(function () {
var food = "noodle";
var eat = function () {
console.log(`eat ${food}`);
};
eat();//eat noodle
})();js
function A() {
for (var i = 0; i < 10; i++) {
setTimeout(function () {
console.log(i);//输出10次9
}, 1000)
}
}
A();
for (var i = 0; i < 3; i++) {
(function (i) {
setTimeout(function () {
console.log(i); //1s输出0 1 2 因为此处使用闭包记录了词法环境
}, 1000)
}(i));
}