这道面试题不是特别变态
题目
var foo = function () {
console.log("foo1")
}
foo()
var foo = function () {
console.log("foo2")
}
foo()
function foo() {
console.log("foo1")
}
foo()
function foo() {
console.log("foo2")
}
foo()
知识点
这道面试题涉及到两个知识点,一个是变量提升,一个是变量的声明与赋值,搞懂这两个问题,这题就迎刃而解了。
变量提升
当你使用
var
关键字(注意,这个特性不适用于let
和const
)声明一个变量时,JavaScript会将这个声明移动到其所在作用域的顶部。但是,请注意,只有声明被提升,赋值不会。
JavaScript会将这个声明移动到其所在作用域的顶部。 这句话应该很好理解吧。就是我定义的变量,都会被放到代码最顶处,不管你书写位置在哪。
我们着重看变量的声明与赋值。
变量的声明与赋值
怎么去理解只有声明被提升,赋值不会这句话呢?
我们需要去先去理解什么是声明,什么是赋值;
就比如下面代码:
var a = 1
我们可以把它看成是两行代码组成,分别是
var a = undefined;//声明部分
a = 1 //赋值部分;
相信大家看完这个例子,应该就明白了。大概可以这么去理解,声明就是表明存在这么个东西,但是这个东西是什么,我不去管。赋值就是给存在的这个东西赋予明确的值;
懂了什么是声明,什么是赋值之后,就很容易理解“只有声明被提升,赋值不会”这句话了。
我们再通过一个例子去解释这句话
console.log(a);
var a = 1;
程序会报错吗?答案是不会的。它会输出undefined
。为什么是undefined
呢?因为a = 1
这行代码声明被提升了,而赋值没有被提升。
“首先声明被提升到作用域顶部,但是赋值是不变的”,因此代码实际实际效果可以等同于如下代码。在执行到第二行时,a
未被赋值,它此时还是默认值undefined
,所以输出结果是undefined
var a = undefined;
console.log(a);
a = 1;
欸?当我们声明了一个变量会发生声明提升,赋值不提示的情况,那么函数呢?我声明一个函数,它的声明和赋值是什么情况?声明会不会提升啊?赋值呢?
比如下面代码:
console.log(a);
var a = function() {
console.log('fun');
};
它还是会打印undefined
,因为它实际效果是这样的
var a = undefined;
console.log(a);
a = function() {
console.log('fun');
};
好,这道面试题的关键点快来了。下面情况会发生什么?
a()
var a = function() {
console.log('fun');
};
结果是Uncaught TypeError: a is not a function
。这大家是很容易理解的,因为我们上面都打印a
了,它是undefined
么,因此报错a
不是一个函数。这不是显而易见嘛!
但是把代码改成下面这段就不会出问题了,它会正常打印fun,这是为什么呢?
a()
function a() {
console.log('fun');
};
原因在于此时的a函数,它是通过function
声明的,它是一个完整的函数声明,也就是说没有涉及到赋值操作。
如何理解这句话呢?也就是说,如果直接通过function
声明的函数,它直接在声明的时候就进行了赋值操作,而不是先声明它,并设置一个undefined
,然后进行赋值操作。
最终的代码可以等同于
function a = function() {console.log('fun')}
a()
看到没,它将a直接提到了最顶部,并且给它声明,它就是一个函数,这个函数要干什么干什么。而不像之前那样,我先给它定义个初始值undefined
,然后再去赋值。
这样的话,执行a的时候,就不会报错,能够正确输出值。
不行,我还的给大家画一幅图来解释下吧。(因为我当初理解这块的时候就理解了好久,所以才如此啰嗦给大家讲解,属实抱歉。)
解答
具备以上知识后,就可以发现,它题目代码可以等同于如下;
var foo = undefined;
var foo = undefined;
function foo = function foo() {
console.log("foo1")
}
function foo = function foo() {
console.log("foo2")
}
foo = function () {
console.log("foo1")
}
foo()
foo = function () {
console.log("foo2")
}
foo()
foo()
foo()
这下子结果就一目了然了吧。先foo1,然后三个foo2。
小伙伴们,以上是我的一个理解,欢迎大家批评指正。
转载自:https://juejin.cn/post/7369813870633812019