JavaScript的作用域
JavaScript的作用域
作用域总共有两种模式,词法作用域
和动态作用域
词法作用域是由开发者在写代码时,将变量和块作用域写在哪里而决定的。
动态作用域是运行时确定的。
JavaScript
只有词法作用域,也就是我们说的作用域链,一层一层的嵌套,但this
机制很像动态作用域,它也是在运行时决定的。
function foo(){
// 词法作用域 2 -- 动态作用域 3
console.log(a);
}
function bar(){
var a = 3;
foo();
}
var a = 2;
bar();
这段代码,以词法作用域来看会输出2,如果是动态作用域的模型,会输出3,因为动态作用域是在运行时决定的,当foo()
无法找到a的变量引用时,会顺着调用栈在调用foo()
的地方去找a,而不是在词法作用域链上去找a,而foo
是在bar
里调用的,在bar里找到了值为3的a,所以动态作用域的模型会输出3。
上面只要了解就够了,接下来主要是说函数作用域的事
function foo(){
var a = 1;
console.log(a); // 1
}
function bar(){
var a = 2;
console.log(a);// 2
}
foo();
bar();
从这里可以看出,在不同的函数中,相同名字的变量,但它们并不是同一个变量,这就是函数作用域。
接下来看稍微复杂的
function bar(){
var a = 2;
console.log(a);// 2
function foo(){
var a = 1;
console.log(a); // 1
}
foo()
}
bar();
经过这两段代码,可以知道不管函数是否嵌套,里面的同名变量都是互不影响的。
函数作用域是如何查找变量的
var a = 1;
var b = 2;
var c = 10;
function bar(){
b = 10; // 通过LSH引用,找到了全局作用域的b,再赋值
var c = 20;
function foo(){
console.log(a); // 1
console.log(c); // 20
}
foo()
}
bar();
console.log(b); // 10
词法作用域在查找变量是往作用域一层一层找的。
在foo
函数要输出a,会先在自己的作用域里找a这个变量,找不到,就会去父级作用域,这里是bar的作用域找,但是很明显,依然找不到,所以再到上一层作用域,这时已经到全局作用域了,发现找到了,于是就输出a的值,如果全局作用域也没有找到就会报错。
而foo在找c的时候,已经在bar的作用域找到了,所以就不会再去全局作用域找了。
而bar的b,也是这样,在自己的作用域找不到,就去它的父级作用域找。