面试题
console.log(a)
var a = 10
function a() {}
console.log(a)
!function () {
console.log(a)
a = 5
console.log(a)
var a = 20
console.log(window.a)
}
();
console.log(a)
前置知识
变量提升 (Hoisting)
介绍变量提升之前,我们先通过下面这段代码,来看看什么是 JavaScript 中的声明和赋值
var name = 'givencui' // 初始化
等价写法
var name // 声明部分
name = 'givencui' // 赋值部分
再来看看, 函数的声明和赋值 参考: MDN - 函数表达式
function foo(){
console.log('foo')
}
var bar = function(){
console.log('bar')
}
如图
好了,理解了声明和赋值操作,那接下来我们就可以聊聊什么是变量提升了。
所谓的变量提升,是指在 JavaScript 代码执行过程中,JavaScript 引擎把变量的声明部分
和函数的声明部分
提升到代码开头的“行为”。变量被提升后,会给变量设置默认值,这个默认值就是我们熟悉的 undefined。
JS 代码的执行流程
JavaScript 代码的执行流程从概念的字面意义上来看,“变量提升”意味着变量和函数的声明会在物理层面移动到代码的最前面,正如我们所模拟的那样。但,这并不准确。实际上变量和函数声明在代码里的位置是不会改变的,而且是在编译阶段被 JavaScript 引擎放入内存中。对,你没听错,一段 JavaScript 代码在执行之前需要被 JavaScript 引擎编译,编译完成之后,才会进入执行阶段。大致流程你可以参考下图:
基础问题
console.log(a) // undefined
var a = 10
console.log(a) // fn a
function a() {}
进阶问题
case1: 变量和函数同名的提升
可以在 chrome devTools 中验证
console.log(a) // fn a
var a = 10
function a() {}
console.log(a) // fn a
function a() {}
var a = 10
结论
var
声明的变量 和函数声明
都存在变量提升- 同名变量和函数发生声明提升时, 函数声明优先级更高
解答开头的题目:
case2: 函数为 IIFE
var a = 1;
(function a() {
a = 2
console.log(a)
})()
console.log(a)
运行结果如下:
验证
var a = 1;
(function a() {
console.log(Object.getOwnPropertyDescriptor(a, 'name'))
a = 2 // 赋值失败
console.log(a)
})()
console.log(a)
严格模式下会报错
var a = 1;
(function a() {
"use strict";
a = 2
console.log(a)
})()
console.log(a)
结论:
IIFE
本质是匿名函数表达式立即调用, 不是函数声明- 函数表达式的函数名是只读的, 非严格模式下会赋值失败, 严格模式下会报错
楼主残忍的关闭了评论