foo(); var foo; function foo(){ console.log(1); } foo = function(){ console.log(2); }
参考答案
答案: 1
引擎会在解释JavaScript代码之前首先对齐进行编译,编译过程中的一部分工作就是找到所有的声明,并用合适的作用域将他们关联起来,这也正是词法作用域的核心内容。
简单说就是在js代码执行前引擎会先进行预编译,预编译期间会将变量声明与函数声明提升至其对应作用域的最顶端。
变量提升
变量声明的提升是以变量所处的第一层词法作用域为“单位”的,即全局作用域中声明的变量会提升至全局最顶层,函数内声明的变量只会提升至该函数作用域最顶层。那么开始的一段代码经过预编译则变为:
var a; console.log(a); // undefined a = "a"; var foo = () => { var a; // 全局变量会被局部作用域中的同名变量覆盖 console.log(a); // undefined a = "a1"; } foo();
输出undefined就很明了。
ES6新增了let和const关键字,使得js也有了“块”级作用域,而且使用let和const 声明的变量和函数是不存在提升现象的,比较有利于我们养成良好的编程习惯。
函数提升
有了上面变量提升的说明,函数提升理解起来就比较容易了,但较之变量提升,函数的提升还是有区别的。举例说明:
console.log(foo1); // [Function: foo1] foo1(); // foo1 console.log(foo2); // undefined foo2(); // TypeError: foo2 is not a function function foo1 () { console.log("foo1"); }; var foo2 = function () { console.log("foo2"); };
即函数提升只会提升函数声明,而不会提升函数表达式。
正文结束
Ctrl + Enter