Javascript的作用域与作用域链

不提ES6新声明的作用域声明(let等),单纯看js的作用域。

作用域的定义:作用域是某一变量和方法具有访问权限的代码控件。

在JS中作用域主要由全局作用域和本地(函数)作用域两种,全局变量在所有函数中都能被访问到,本地作用域声明的变量只能在当前函数代码块中被访问;

例如:

1、全局变量能被直接访问

1
2
var a = 0;
alert(a);//=> 0

2、全局变量能再函数内部访问

1
2
3
4
5
var a = 0;
function test(){
alert(a);
}
test();//=> 0

3、本地作用域(函数内部)声明的变量能被本作用域(本函数)内部直接访问

1
2
3
4
5
function test(){
var a = 0;
alert(a);
}
test();//=> 0

4、本地作用域(函数内部)声明的变量不能在作用域外(函数外部)被访问

1
2
3
4
5
function test(){
var a = 0;
}
test();
alert(a);//=> undefined

5、本地作用域声明的变量不能在其外部的别的本地作用域中被访问

1
2
3
4
5
6
7
8
function test(){
var a = 0;
}
function run(){
alert(a);
}
test();
run();//=> undefined

6、本地作用域内部的作用域能访问到上级声明的变量

1
2
3
4
5
6
7
function test(){
var a = 0;
function child(){
alert(a);
}
}
test();//=>0

7、本地作用域声明的变量级别比全局变量高,能在作用域内覆盖全局变量声明

1
2
3
4
5
6
7
var a - 0;
function test(){
var a = 1;
alert(a);
}
test();//=> 1
alert(a);//=> 0

由此可知,js的作用域是从上往下继承,作用域内部函数能访问本作用域声明的函数与外部作用域生成的函数。

由此可以明确js的作用域链概念。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
var a = 0;
function parent(){
alert(a);
function child1(){
var a = 1;
alert(a);
}
function child2(){
alert(a);
}
}
parent();//=> 0,=> 1,=>0
alert(a);//=> 0

parent()内第一个alert(a)的作用域链是parent()->window,所以此时a是0;

child1()内alert(a)的作用域链是child1()->parent()->window,在child1中重新声明了a的值,覆盖了全局变量的值因此此时a是1;

child2()中alert(a)的作用域链是child2()->parent()->window,与child1中声明的a=1毫无关联,因此此时的a的值还是0;

最后一个alert(a)作用域链是window,此时a的值为0;

js的作用域与作用域链的概念可以简单清晰的按如上描述。