前端面试系列-JavaScript作用域和作用域链

我心飞翔 分类:javascript

当JavaScript代码执行一段可执行代码(executable code)时,会创建对应的执行上下文(execution context)。对于每个执行上下文,都有三个重要属性:

  • 变量对象(Variable object,VO)
  • 作用域链(Scope chain)
  • this

那么作用域链是什么呢?一起来看看。

作用域

作用域,就是变量或者是函数能作用的范围。

1.全局作用域

除了函数中定义的变量之外,都是全局作用域。

var a = 1;
function bar(){
    console.log(a);
}
bar();//1
 

a就是全局变量,在函数里也可以访问a

2.函数作用域

创建函数后在花括号中声明的一些语句或变量只在当前函数中起作用。

var a = 10;
function bar(){
   var a  = 20;
    console.log(a);
}
console.log(a);//10,取的全局作用域中的a
bar();//20,取的局部作用域中的a
 

3.块级作用域

ES6带来的新特性,在语句块中声明的语句或变量只在当前语句块中起作用。

函数作用域和块级作用域根本没有直接关系,函数作用域在ES5和ES6作用完全一样,变量不论是使用var声明还是使用了let ,const声明在外部都是不可以访问的。

块级作用域指的就是使用 if () { }; while ( ) { } ...这些语句所形成的语句块 , 并且其中变量必须使用let或const声明(否则就不是块级作用域了),保证了外部不可以访问语句块中的变量。

if(true) {
let name='douqing';
console.log(name); // douqing
}
console.log(name); // ReferenceError: name is not defined
 

经典例子

for(var i=0;i<4;i++){
    setTimeout(function(){
    	console.log(i);
    },200);
}
//4 4 4 4
 

利用函数形成函数作用域

for(var i=0;i<4;i++){
    (function(j){
            setTimeout(function(){
    	console.log(j);
    },200);
    })(i)
}
//0 1 2 3
 

利用let形成块级作用域

for(leti=0;i<4;i++){
    setTimeout(function(){
    	console.log(i);
    },200);
}
//0 1 2 3
 

作用域链

当查找变量的时候,会先从当前作用域的变量对象中查找,如果没有找到,就会从父级作用域(上层环境)的变量对象中查找,一直找到全局作用域的变量对象,也就是全局对象。这样由多个作用域的变量对象构成的链表就叫做作用域链。它由当前环境与上层环境的一系列变量对象组成,保证了当前执行环境对符合访问权限的变量和函数的有序访问。

var a = 20;
function test() {
    var b = a + 10;//当前作用域没有a,往上找,找到a = 20;
    function innerTest() {
        var c = 10;
        return b + c;//当前作用域没有b,往上找,找到b = a+10;
    }
    console.log(d);//Uncaught ReferenceError: d is not defined,一直往上找,最终也没找到d,所以报错
    return innerTest();
}
test();//40
 

回复

我来回复
  • 暂无回复内容