双11期|变量提升与函数提升
tips:每个技术点都值得优学优写:11期
通常我们认为变量需要先声明再使用,才不会报错,但在 JavaScript 种, 先使用一个变量后面再使用 var 声名赋值,不会被抛出异常,而是该值为 undefined。
JavaScript 变量感觉上是被“提升”或移到了函数或语句的最前面,这种现象被人称为“变量提升”。
对于 JavaScript 中的函数来说,也有“函数提升”的现象。
变量提升
“变量提升”的存在,使得变量像是声明提前,声明语句被移动到环境的顶部似得。 但“变量提升”(声明提前),在使用不同的关键字声明的时候,表现又不尽一致。
例如下面的例子。
// 先使用变量 x,再通过 var 声明并初始化赋值3给它。此时提前使用变量 x 不会抛出异常,x 的值为 undefined。
console.log(x === undefined) // true
console.log(x) // undefined
var x = 3
// 变量依然被“提升”了,但不会被赋予初始值,提前使用变量 y,将抛出引用错误(ReferenceError)。
console.log(y)
let y = 2
// const 和 let 的情况一样,也会抛出引用错误(ReferenceError)
console.log(z)
const z = 1
使用 var 声明的变量,存在变量提升现象,但不会抛出异常,默认值会被设置为 undefined。
在 ECMAScript 6 中,let 和 const 同样会被提升变量到代码块的顶部但是不会被赋予初始值。 在变量声明之前引用这个变量, 将抛出引用错误(ReferenceError)。 这个变量将从代码块一开始的时候就处在一个“暂时性死区”,直到这个变量被声明为止。
下面是一张使用 let 声明的变量被提前使用的报错截图。
函数提升
JavaScript 中,函数 function 也存在“声明提前”的现象。 不同的是对于函数来说,只有函数声明会被提升到顶部,而函数表达式不会被提升。
例如下面的例子。
/* 函数声明:函数提升了,成功执行了打印语句,没有抛出异常 */
test(); // "测试函数声明提升"
function test() {
console.log("测试函数声明提升");
}
/* 函数表达式:没有被提升,抛出了 typeError: testExpression is not a function */
testExpression(); // 类型错误:baz 不是一个函数
var testExpression = function() {
console.log("测试函数表达式提升");
};
这是一张前面的例子,关于函数提升和函数表达式不提升的测试截图:
几个有趣的例子
例子一:执行下面的代码,控制台输出结果是什么?
var test = function () {
console.log(1)
}
function test () {
console.log(2)
}
test()
例子二:执行下面的代码,控制台输出结果是什么?
function test () {
console.log(2)
}
var test = function () {
console.log(1)
}
test()
例子三:执行下面的代码,控制台输出结果是什么?
var test = "1"
function test () {
console.log(2)
}
test()
例子四:执行下面的代码,控制台输出结果是什么?
let test = function () {
console.log(2)
}
function test () {
console.log(2)
}
test()
上面几个例子执行结果是啥,欢迎评论区分享你的答案。 关于错误类型,可以参考这篇 基本对象Error及8种错误类型