这是《你不晓得的 JavaScript》中的一个典型问题,个人感觉挺重要的,所以对其总结演绎。
1. 在书中的鸡指什么?蛋指什么?
鸡指赋值,蛋指申明。
在 JS 中引擎会在解释 JavaScript 之前对其进行编译。编译这一步会先找到所有的申明, 换句话说所有变量或者函数的申明会在任何代码执行之前先被解决
引擎:负责 JavaScript 程序的编译及执行过程
编译器:负责语法分析及代码生成
对于 var a = 2
在 JavaScript 中会被分成两部:
1. var a;(编译)
2. a=2;(执行)
编译器执行过程:
1. 遇到 var a,编译器会询问作用域是否曾经有一个该名称的变量存在于同一个作用域的汇合中。如果是,编译器会疏忽该申明,持续进行编译;否则它会要求作用域在以后作用域的汇合中申明一个新的变量,并命名为 a。
2. 接下来编译器会为引擎生成运行时所需的代码,这些代码被用来解决 a = 2 这个赋值操作。引擎运行时会首先询问作用域,在以后的作用域汇合中是否存在一个叫作 a 的变量。如果是,引擎就会应用这个变量;如果否,引擎会持续查找该变量。
这时来看书中的问题:
a=2;
var a;
console.log(a);//2
console.log("--------------");
console.log(a2);//undefined
var a2=2;
在 JS 理论执行中会被转成
var a;
a=2;
console.log(a)
var a2;
console.log(a2);
a2=2;
这样再看为什么一个输入 2 一个输入 undefined 就高深莫测了。
书中还有一个留神点: 函数申明的优先级比变量高
foo();//1
var foo;
function foo(){console.log(1);
}
foo=function(){console.log(2);
}
总结:
1. 在 JS 执行前会先编译,找出所有变量,函数的申明。
2. 如果反复申明变量且没赋初值会疏忽申明(可看上编译器执行过程),如果赋初值会笼罩后面该变量的值。