前言
在我们的印象中,当提到 JavaScript 中的变量提升,我们想到的是[变量和函数的声明在物理层面移动到代码的最前面[。当然这么说不大准确,变量和函数声明在代码里的位置是不会变的,而是在编译阶段被放入内存中。
可是如果我问你:let 到底有没有提升?如果有,var / let / function三者的变量提升一致吗?此时你的答案是什么?
接下来让我们来探讨这两个问题,如有错误敬请指正。
1. let存在提升
对于 let 是否存在提升这个问题,让我们先来看以下这段代码:
a = "global"; (function() { console.log(a); // undefined, 而不是打印出global var a; }()); { console.log(a); // Uncaught ReferenceError: Cannot access 'a' before initialization let a = 1; }
对于在函数作用域下打印出 undefined ,我们应该不奇怪。但引起我注意的是在块作用域下,抛出引用错误的原因是在初始化之前找不到 a 。那有没有可能 a 在 创建过程被提升 ?而在我发现ES文档中存在 [var/let hoisting] ,这让我有理由猜测 let 存在提升,只是由于 暂时性死区 的原因,我们不能在 let a 之前使用 a 。
为了证明我的猜想,我想先从 let 声明的创建、初始化和赋值过程入手。
{ let a = 0; a = 1; }
上述的代码块中发生的过程如下:
找到所有用 let 声明的变量,在环境创建变量; 执行代码; 执行 a=0 ,将 a 初始化为1; 执行 a=1 ,对 a 进行赋值。由该过程可知,如果我们在 创建完变量后和初始化之前 执行 log() 方法,控制台将会报错:
let a = 'global' { console.log(a) // Uncaught ReferenceError: Cannot access 'a' before initialization let a = 1 }
由此一来我们就可以知道了 let 在创建的过程被提升,而在初始化过程没有被提升。
2. var/function的变量提升
接下来我们来看看 function/var 的创建、初始化和赋值过程,由此看看能否探究出它们的差别。
2.1 var的变量提升
function foo() { console.log(a); // undefined var a = 0; var b = 1; } foo();
当我们执行 foo() 时,发生以下过程(较为省略):
为 foo 创建环境; 找到 foo 中所有被 var 声明的变量,在这个环境中创建变量; 将变量初始化为 undefined; 执行代码; 将 a 赋值为0, b 赋值为1。由此我们可以知道 var 声明在代码执行前创建变量并初始化,所以当我们在 var a = 0 之前执行 log(a) 方法会得到 undefined 的结果。
2.2 function的变量提升
foo('btqf'); function foo(name) { console.log("my name is" + name) // my name is btqf }
当我们执行 foo 函数时,发生以下过程:
找到所有 function 声明的变量,在环境中创建变量; 将这些变量初始化并赋值; 执行代码。由此可见, function 声明在代码执行前就创建、初始化并赋值。
3. 总结
let 的「创建」过程被提升了,但是初始化没有提升。 var 的「创建」和「初始化」都被提升了。 function 的「创建」「初始化」和「赋值」都被提升了。 函数和变量相比,会被优先提升,即函数会被提升到更靠前的位置。值得一提的是 const 与 let 基本类似,唯一的区别在于 const 只有创建和初始化,没有赋值过程。
到此这篇关于深入了解JavaScript中let/var/function的变量提升的文章就介绍到这了,更多相关let/var/function变量提升内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
查看更多关于深入了解JavaScript中let/var/function的变量提升的详细内容...