话不多说,这是阿里的一道前端面试题
var c = 1;
function c(c) {
console.log(c);
var c = 3;
}
c(2);
要搞定这一题,首先要把明白虽然JS是一门解释性语言,但浏览器JS引擎在执行一段程序之前,其中的编译器模块会对JS待执行的JS代码进行预编译,对于理解声明的提升来说,预编译的过程其实就是在适当的作用域中处理变量和函数声明的过程。明白了这一点我们再来谈变量提升。先来看一段简单的代码
console.log(a);
var a=2;
仅仅从词法层面上来考虑该代码执行顺序,由于我们并没有声明一个变量a,直接在控制台打印它,根据我们的经验浏览器会给我们抛出变量不存在(ReferenceError)但实际上却会给我们打印出undefined,这是因为预编译的过程将将变量a的声明提升到当前作用域的顶端,而赋值语句仍然停留在原地,经过预编译等待执行的代码是这样的(不严密便于理解)
var a;
console.log(a);
a=2
而后JS引擎执行这段代码,a变量声明未赋值故打印出undefined。
好了,现在我们已经具备解决面试题的能力了,Let's begin!
这里我们又遇到了一个问题,函数声明和变量声明同时出现在了该段代码中...这里我们要记住函数声明会优先被提升,同时若函数声明被提升之后编译器又遇到一个要提升同名变量声明,不好意思老弟你将被忽略,这段面试代码预编译后的词法结构如下
function c(){
//这个函数与解决问题无关,先行搁置一会讨论
}
var c;//被编译器忽略
c=1;
c(2);
bangbang~执行,c被赋给一个值变量,你却要把它当成函数调用,不好意思浏览器不干了,抛给你类型错误异常(TypeError)
这道面试题已经被我们解决。这时我突然发现这个函数的形参和内部声明的变量同名这也是一个让人迷惑的问题,下一篇文章写一下这个问题