作用域作用域链自由变量变量提升

Posted 郭郭郭牧鑫

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了作用域作用域链自由变量变量提升相关的知识,希望对你有一定的参考价值。

作用域

  作用域经常被用来配合js引擎去查询访问权限。比如js引擎想要调用某一个变量就会先询问作用域自己能否取到该变量。得到作用域的许可后再执行后续步骤。引擎负责从头到尾整个js程序的编译和执行过程。
  所以作用域是负责收集、维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符的访问权限。
作用域分类

全局作用域(globe scope)和局部作用域(local scope)

全局作用域可以在代码中的任何地方都能被访问,例如:

var name1="haha";
function changName(){
    var name2="xixi";
    console.log(name1); // haha
    console.log(name2);// xixi
}
changName();
console.log(name1);//haha
console.log(name2);//Uncaught ReferenceError: name2 is not defined

其中,name1具有全局作用域,因此在第4行和第8行都会在控制台上输出 haha。name2定义在changName()函数内部,具有局部作用域,因此在第9行,解析器找不到变量name2,抛出错误。
  另外,在函数中声明变量时,如果省略 var 操作符,那么声明的变量就是全局变量,拥有全局作用域,但是不推荐这种做法,因为在局部作用域中很难维护定义的全局变量。

再者,window对象的内置属性都拥有全局作用域。

局部作用域一般只在固定的代码片段内可以访问得到,例如上述代码中的name2,只有在函数内部可以访问得到。

作用域链

在函数创建的时候,作用域链就形成了

变量的查找机制:当在一个作用域中访问一个变量的时候,首先查找的当前自己的作用域(AO)如果没有找到,就会去查询去查询父作用域的AO,如果也没有,就一直查询到全局gobal context 对象,找到了就返回,找不到就报错。这个查询层层递进形成一个链条 ,这个链条就是 作用域链

函数在被定义的时候,就通过{构造函数}.prototype.contructor.[[scope]]记录作用域链,并且函数会记住创建这个函数的环境(context)

自由变量

假如在全局中定义了一个变量,在函数中使用了这个变量,这个变量就是自由变量,也就是,凡是跨了自己的作用域的变量都叫自由变量

变量提升(js执行之前,浏览器将var提前声明为undefined,将function提前声明和定义)

变量提升只发生在当前作用域:
(1)开始加载页面时,只对全局变量进行提升,在函数内的声明的变量不被提升。
(2)执行函数时,私有作用域形成后,先形参赋值,然后变量提升,最后执行代码

在编译阶段,变量会被提前进行处理,如果有函数定义,则优先级高于变量定义

强调:函数的定义才会被提升,表达式不会

在ES6中使用 let const 定义变量,不会发生变量提升,同时不会出现重复变量

以上是关于作用域作用域链自由变量变量提升的主要内容,如果未能解决你的问题,请参考以下文章

作用域作用域链自由变量变量提升

JavaScript 作用域作用域链变量提升

JavaScript 作用域作用域链变量提升

原型模式故事链--JS变量作用域作用域链闭包

JavaScript作用域:全局作用域局部作用域块级作用域作用域链变量提升

深入理解javascript原型和闭包(14)——从自由变量到作用域链