前言:做为解释性语言的JS,在执行前会先进行预编译。理解了预编译,JS中的变量提高就能够更快的搞懂啦!javascript
在讲解预编译前,先讲解个知识点。敲黑板啦!小伙伴们不要光看,本身打打代码才知道。java
window
全部。以下所示,即window.a = 10
。这个
window
究竟是什么,其实它就是一个全局对象,提供了一个全局做用域。在全局做用域声明变量,就是为全局对象添加属性。即在window对象中添加了一个属性a,其值为10。bash
<script type="text/javascript">
a = 10;
console.log(a);//访问这个a实际上就是访问window.a
<script>
复制代码
window.a和window.b
会输出什么呢?
<script type="text/javascript">
function test() {
var a = b = 123;
}
test();
<script>
复制代码
window
的一个属性,因此能够经过window.变量名访问
。window
的属性。<script type="text/javascript">
var b = 20;
console.log(b);
<script>
复制代码
看一段代码函数
undefined
,那么undefined
是什么意思呢?是var
声明了变量可是未对它进行初始化。因此先让这个变量初始化为undefined
,也就是先让b=undefined
直到真正赋值阶段时才是20。Uncaught ReferenceError: Cannot access 'a' before initialization
。翻译过来的意思就是没法在初始化以前访问a。<script type="text/javascript">
//var
console.log(b);//undefined
var b = 20;
//let
console.log(a);//Uncaught ReferenceError: Cannot access 'a' before initialization
let a = 10;
<script>
复制代码
为何
var
和let
二者不同呢?先来说讲var
吧ui
var b = 20;
包括两个步骤:<script type="text/javascript">
var b;//该声明提高了,提高到做用域的顶部。
console.log(b);//undefined
b = 20;
<script>
复制代码
var的提高实际上是建立和初始化都提高了。也许你又会问那为何初始化的值是undefined。这和执行前发生的预编译有关。spa
先看下面的代码到底输出什么?既有函数又有变量,并且还同名,那变量的声明提高和函数提高到底谁的优先级高呢?想必是很懵逼吧,不要紧,跟着我一块儿来一步一步理解下。翻译
function test(a)
{
console.log(a);
var a = 123;
console.log(a);
function a() {}
console.log(a);
var b = function () {}
console.log(b);
function d() {}
}
test(1);
复制代码
AO{}
复制代码
AO{
形参或变量声明:undefined
}
也就是
AO{
a:undefined,//这里形参function test(a)和变量var a都是,写一次就行了
b:undefined
}
复制代码
AO{
形参或变量声明:实参
}
也就是
AO{
a:1,
b:undefined
}
复制代码
AO{
形参或变量声明:函数体
}
也就是
AO{
a:function a() {},//函数声明
b:undefined,
//注意了 var b = function () {}这个不是函数声明,是函数表达式,因此b的值仍是undefined
d:function d() {}//函数声明
}
复制代码
注意:要打印的值都从预编译后的AO对象中取值code
function test(a)
{
//1.输出function a() {}
console.log(a);
/*2. 预编译时已经变量提高了,可是赋值尚未操做。因此此时AO对象中a的值改变为123
AO{
a:123,
b:undefined,
d:function d() {}
}
*/
a = 123;
//3.输出:123
console.log(a);
function a() {}
//4.输出123
console.log(a);
/*5.改变AO对象中b的值
AO{
a:123,
b:function () {},
d:function d() {}
}
*/
var b = function () {}
//6.输出function () {}
console.log(b);
function d() {}
}
复制代码
实际输出结果和分析的同样。棒棒哒!cdn
理解了预编译后,想必var
的变量提高弄明白了吧!var提高指的是建立和初始化都被提高了。因此下面代码输出的结果才是undefined对象
console.log(a);
var a = 20;
复制代码
console.log(a);//Uncaught ReferenceError: Cannot access 'a' before initialization
let a = 10;
复制代码
对于上面的结果也许你会说:那let不就没有提高。这就错了,其实它是有提高的,只不过提高的只有建立过程,初始化时没有提高的。看码
let a = 1;
{
console.log(a);
let a = 2;
}
复制代码
若是let不存在提高,那么应该输出1。可是却报错 Uncaught ReferenceError: Cannot access 'a' before initialization。这就说明let存在提高。只是被存在“暂存死区”中。只有当初始化后才能被引用。
var
:【建立】和【初始化】都被提高function
:总体提高,也就是【建立】【初始化】【赋值】都被提高let
:【建立】过程提高,但初始化没有提高。