变量提升与函数提升,挑战下这几个例子?

3,817 阅读3分钟

双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 声明的变量被提前使用的报错截图。

image.png

函数提升

JavaScript 中,函数 function 也存在“声明提前”的现象。 不同的是对于函数来说,只有函数声明会被提升到顶部,而函数表达式不会被提升。

例如下面的例子。

/* 函数声明:函数提升了,成功执行了打印语句,没有抛出异常 */
test(); // "测试函数声明提升"

function test() {
  console.log("测试函数声明提升");
}


/* 函数表达式:没有被提升,抛出了 typeError: testExpression is not a function */
testExpression(); // 类型错误:baz 不是一个函数
var testExpression = function() {
  console.log("测试函数表达式提升");
};

这是一张前面的例子,关于函数提升和函数表达式不提升的测试截图:

image.png

几个有趣的例子

例子一:执行下面的代码,控制台输出结果是什么?

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种错误类型