作用域
scope
1.函数创建时,生成的一个js内部隐式属性;
2.函数存储作用域链的容器;
AO/GO
AO:函数的执行期上下文
GO:全局的执行期上下文
函数执行完成后,AO是要销毁的;AO是一个即使存储容器。
function a(){ function b(){ function c(){} c(): } b(); } a(); a定义:a.[[scope]] -> 0 : GO a执行:a.[[scope]] -> 0 : a -> AO 1 : GO b定义:b.[[scope]] -> 0 : a -> AO 1 : GO b执行:b.[[scope]] -> 0 : b -> AO 1 : a ->AO 2 : GO c定义:c.[[scope]] -> 0 : b -> AO 1 : a -> AO 2 : GO c执行:c.[[scope]] -> 0 : c -> AO 1 : b -> AO 2 : a -> AO 3 : GO c结束:c.[[scope]] -> 0 : b -> AO 1 : a -> AO 2 : GO b结束:b.[[scope]] -> 0 : a -> AO 1 : GO c.[[scope]] 完全销毁 a结束:a.[[scope]] -> 0 : GO b.[[scope]] 完全销毁
JavaScript 采用的是词法作用域(静态作用域),函数的作用域在函数定义的时候就决定了,而不是函数调用的时候才决定的。
举个例子:
var value = 1;
function foo() {
console.log(value);
}
function bar() {
var value = 2;
foo();
}
bar();
执行 foo 函数,先从 foo 函数内部查找是否有局部变量 value,
如果没有,就根据书写的位置,查找上面一层的代码,也就是 value 等于 1,所以结果会打印 1。
思考:
var a = 10;
var o = {
a:11,
b:{
fn:function(){
console.log(a);
}
}
}
o.b.fn();
执行o.b.fn,先从 fn 函数内部查找是否有局部变量a,
如果没有,就根据书写的位置,查找o上面一层的代码,也就是 a 等于 10,所以结果会打印 10。
值得注意的是:
如果是一个函数里又嵌套一个完整的函数
里面的那个函数,其作用域必然是外层的函数
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
checkscope()();
输出:local scope
注意
1.函数的作用域在函数定义的时候就决定了,而不是函数调用的时候才决定的
2.this指调用函数所处的环境(二者不要混淆)
3.作用域可以一层一层往外找;this则是按着原形链去访问它父级对象