变量提升原理
Posted bengbengbeng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了变量提升原理相关的知识,希望对你有一定的参考价值。
关于变量要提前声明,作为前端程序员我们都知道要这么做。可是为什么要这么做呢?
今天我去面试,被一个面试官问到了这个问题,当时就懵逼了。所以我就研究了一下为什么会变量提升。
研究完才发现,之前有看过这样的文章,可是没有真正弄懂。所以写下了这篇博客。
首先要了解两个名词。
JS作用域和词法分析。
如何了解JS作用域呢? 那么就要了解什么是执行环境。
执行环境:执行环境定义了变量和函数有权访问的其他数据。每个执行环境都有对应的变量对象(Variable Object),保存着该环境中定义的变量和函数。我们无法通过代码来访问它,但是解析器在处理数据的时候会在后台使用到它。
全局执行环境:最外围的执行环境。我们可以认为是windows对象,因此所有的全局变量和函数都是做为windows的属性和方法创建的。
局部执行环境:每个函数都有自己的执行环境,当执行流进入到一个函数时,函数的环境就被推入到执行栈当中,当函数执行完毕并且没有引用时,栈将其环境弹出,将控制权返回给之前的执行环境。
全局作用域:可以在代码中的任何地方都能被访问。
局部作用域 : 只有在函数内部才能访问。
作用域链:全局作用域和局部作用域中变量的访问,其实是由作用域链决定的。
&& 每次进入一个新的执行环境,都会创建一个用于搜索变量和函数的作用域链。作用域链是函数被创建的作用域中对象的集合。作用域链可以保证对执行环境有权访问的所有变量和函数的有序访问。
&&作用域链的最前端始终是当前执行的代码所在的环境的变量对象,如果该环境是函数,则将其活动对象作为变量对象,下一个变量对象来自包含环境,下一个变量对象来自包含环境的包含环境,依次往上,直到全局执行变量。
&&标识符解析沿着作用域一级一级的向上搜索标识符的过程。搜索过程始终是从作用域的前端逐渐向后回朔,直到找到标识符。
这就是JS的作用域和作用域链。
词法分析:
在JS代码执行前,会执行词法分析。所以JS运行要分为词法分析和执行两个阶段。
函数在运行的瞬间,会生成一个活动对象Active Object,简称AO。
- 分析形参
- 如果函数有形参,则给当前活动对象增加属性,赋值为undefined。
- 分析变量
- 如果AO上还没有 XXX 属性,则给当前活动对象增加属性,赋值为undefined.
- 如果AO上有 XXX 属性,则不做任何影响。
- 分析函数
- 把函数赋值给 AO.func 属性
- 如果此前 foo 属性已存在,则覆盖。
1 function func(age) { 2 console.log(age); 3 var age = 25; 4 console.log(age); 5 function age() { 6 } 7 console.log(age); 8 9 } 10 func(18);
这是一个函数声明
首先会进行词法分析:
- 分析形参
- AO.age = "undefined";
- 分析变量
- Ao.age = 25;
- 分析函数
- Ao.age = function age(){};
以上是关于变量提升原理的主要内容,如果未能解决你的问题,请参考以下文章