五句话搞定JavaScript作用域
五句话搞定JavaScript作用域(转)
此文针对ES,不涉及ES2015(ES6)
一、“JavaScript中无块级作用域”
- 大括号不是一个作用域。
1
2
3
4
5
6function Main() {
if(true) {
var name = 'JAMES';
}
console.log(name); // JAMES
}
补充:标题之所以添加了引号是因为ES6中引入了let关键字 用于指定变量属于块级作用域
二、JavaScript采用函数作用域
- 在JavaScript中每个函数作为一个作用域,在外部无法访问内部作用域中的变量。
1
2
3
4
5function Main() {
var innerValue = 'ABC';
}
Main();
console.log(innerValue); // Uncaught ReferenceError: innerValue is not defined
三、 JavaScript的作用域链
- 由于JavaScript中的每个函数作为一个作用域,如果出现函数嵌套函数,则就会出现作用域链。
1
2
3
4
5
6
7
8
9
10xo = 'five';
function Func() {
var xo = 'six';
function innerFunc() {
var xo = 'seven';
console.log(xo);
}
innerFunc();
}
Func(); // seven
如上述代码则出现三个作用域组成的作用域链,如果出现作用域链后,那么寻找变量的时候就会出现顺序,对于上述示例:当执行console.log(xo)时,其寻找顺序为根据作用域链从内到外的优先级寻找,如果内层没有就逐步向上找,直到没找到抛出异常。
四、JavaScript的作用域链执行前已经创建
- JavaScript的作用域在执行前已经创建,日后再去执行时只需要按照作用域链去寻找即可。
- 示例一
1
2
3
4
5
6
7
8
9
10xo = 'five';
function Func() {
var xo = 'six';
function innerFunc() {
console.log(xo);
}
return innerFunc;
}
var ret = Func();
ret(); // six
上述代码,在函数被调用之前作用域链已经存在:
全局作用域 -> Func()函数作用域 -> inneFunc()函数作用域。
当执行ret();时,由于其代指的是innerFunc函数,此函数的作用域链在执行之前就被定义为:全局作用域 -> Func()函数作用域 -> inneFunc()函数作用域,所以,在执行ret();时,会根据已经存在的作用域链去寻找变量。
- 示例二
1
2
3
4
5
6
7
8
9
10
11xo = 'five';
function Func() {
var xo = 'six';
function innerFunc() {
console.log(xo);
}
xo = 'seven';
return innerFunc;
}
var ret = Func();
ret(); // seven
上述代码和示例一的目的相同,也是强调在函数调用之前作用域链已经存在:
全局作用域 -> Func()函数作用域 -> inneFunc()函数作用域
- 示例三
1
2
3
4
5
6
7
8
9
10xo = 'five';
function Bar() {
console.log(xo);
}
function Func() {
var xo = 'six';
return Bar;
}
var ret = Func();
ret(); //five
上述代码中,在函数被执行之前就已经创建了两条作用域链:
全局作用域 -> Bar()函数 ;全局作用域 -> Func()函数;当执行ret(),ret执行Bar函数,而Bar的作用域链已经存在,就会根据Bar函数的作用域链去寻找。
五、声明提前
在JavaScript中如果不创建变量,直接去使用则报错:
1
2console.log(xxoo);
// Uncaught ReferenceError: xxoo is not defined如果创建变量而不赋值,则为undefined:
1
2
3var xxoo;
console.log(xxoo);
// undefined在函数内如果这么写:
1
2
3
4
5
6
7
8function Foo() {
console.log(xo);
var xo = 'seven';
console.log(xo);
}
Foo();
// undefined
// seven
上述代码,不报错而是输出undefined,其原因是:JavaScript的函数在执行之前,会将其中的变量全部声明,而不赋值。所以,相当于上述示例三中,函数在“预编译”时,已经执行了var xo;所以上述的代码输出是undefined。