作用域链与闭包

作为一个前端开发,在面试的时候总是会被问到一个很基础的问题,就是作用域链与闭包,我记得当时被问到这个我说:我不太清楚这个但是平常写代码的时候应该用到了但是我不知道。(心里动作:完蛋被刷了)那我根据这个小栗子记录一下吧万一以后忘了:

console.log(a,b);  //undefined*2
变量提升:在浏览器执行我们的js代码之前,会进行一个变量提升,就是将所有带var和function的变量存储到当前作用域中,也就是全局作用域,虽然上述代码是在看起来是使用了a,b之后才用var进行声明的,但是在变量提升的时候,也就是没有执行上面代码的时候,就已经提前把a,b声明过了,所以第一次输出的结果是undefined; var a = 12,b = 12; //变量赋值 function fn(){ console.log(a,b) //undefined,12 var a = b = 13; //等价 var a = 13;b = 13; console.log(a,b); //13,13 } fn();
console.log(a,b); //12,13

函数体第一行:在执行这个函数的时候,会进入到函数内部执行代码,这时候又形成了一个新的作用域叫做私有作用域,在这个私有作用域中,执行代码前又进行了变量提升,所以在函数体的第一条输出语句中,会输出undefined,12,undefined是当前作用域已经被声明了的a,12是到全局作用域下查找到的b;这就是作用域链,在代码执行的过程中,如果遇到一个变量在当前作用域是不存在的那么它会向上一级寻找这个变量,直到找到全局作用域为止,这个查找过程就是作用域链;

 

函数体第二行:在函数体的私有作用域中,把它自己的变量a的值赋予13,把全局作用域里的b改成13;

函数体第三行:这时候全局作用域中a=12,b=13,私有作用域这里a=13,那么这里我们在输出ab的值的时候首先我们会去寻找私有作用域中的变量,再去找全局作用域里的变量,所以输出13,13;

最后一行的输出是输出全局作用域里的变量,为12,13;

闭包:函数执行的时候形成的私有作用域,会把作用域里的所有私有变量保护起来,和外界没有任何管理,函数执行的这个保护机制就是闭包。

闭包里的私有变量包括:形参、带let/const/var/function...的变量

作用域链的查找机制:一开始就定好了,和函数在哪执行的没关系

栗子:

var n = 1;
function fn() {
  var n = 2;
  function f() {
    n--;
    console.log(n);
  }
  f();
  return f;
}
var x = fn();
x();
console.log(n);

  

所得结果为 1,0,1

原文地址:https://www.cnblogs.com/jjbHD/p/13908958.html