let有没有变量提升
在第一次学习let的时候,老师告诉我,let跟var不一样,let不存在变量提升,看下面这个例子:
后来又说到let 有个暂时性死区问题
x = "global";
// function scope:
(function () {
console.log(x); // not "global"
let x;
}());
这里会报错。
我们都知道如果不写let或者var声明,x也会被赋值,虽然这是一种bug,但是在这段代码中,应该是x会变成全局变量。
但是实际上,x并没有在函数中生效!!也就是所谓的let的暂时性死区。let
在{}
内起效果了。你可以理解为暂时性死区让这段代码无法运行,x不能在let
前使用,但是这样并不能帮助我们理解,因为如果说let没有提升,那凭什么遇到这段代码会优先报错。这显然是一个悖论啊。也就是说js内部肯定检测到了let
的某种提升,所以才会出现这种情况。
我这个人非常喜欢转牛角尖,直到我看到这篇文章,我希望你也能看看。 我用了两个月才理解let--作者:方应杭
我来总结一下关于变量提升这一点
1、JS中存在创建、初始化、赋值
例如
x = "global";
// function scope:
(function () {
console.log(x); // 打印undefined
var x;
}());
同样的代码只是let变成了var,但是最后打印出来的结果是undefined。
如果按照创建、初始化、赋值来思考的话,var x =1,
会变成创建并初始化x为undefined(这部分会提升),再赋值x=1。(这部分不会提升)
而let x = 1,会创建一个x变量,初始化并赋值为x =1。(创建会提升,初始化赋值不会提升)。因为创建过程的提升造成暂时性死区问题。
再来看下面这段代码:
console.log(a); //打印出undefined
var a = 1
console.log('-----');
console.log(b);//报错了
let b = 1
上面的b会报错,应当是let让b创建出来了,但是并没有完成初始化。 所以报错了。我们可以理解为初始化是一个必要的过程。
总结:
- let让创建过程被提升了,但是初始化跟赋值没有提升
- var让创建过程和初始化被提升了,但是赋值没有提升
2、函数的提升
我们知道函数存在提升,如果按上述理论来说明的话,函数存在创建、初始化、赋值的提升。
console.log(fn);//打印出函数体,说明提升了
function fn() {}
如果var跟函数同时存在那会取哪个提升呢?看下面的代码
console.log(fn);//函数体
var fn = '123';
function fn() {};
console.log(fn);//打印出123
得出结论:当函数和var同时存在时,var的提升(undefined)会被覆盖
上述代码的取值的结果演变成:
var fn //被覆盖
function fn() {};
console.log(fn);//函数体
fn = '123';
console.log(fn);//打印出123
如果把上述例子的var变成let呢?
会报错。我们可以理解为let创建后发现居然有两个fn!!!滚去改吧。
console.log(fn);//这里报错了
function fn() {};
let fn = '123';
console.log(fn);
大家以后一定要用let 不要再用var这么变态的东西啦。。。
3、const提升
const跟let的差别不大,只是const不能再次赋值而已。(当然这也是const跟let最主要的特性区别啦)~
那么我们再来回顾一下暂时性死区。
暂时性死区,其实就是一个没有完成初始化而导致的结果。
总结一下变态的var的一些题目
// 代码段1
for (var i = 0; i < 5; i++) {
setTimeout(() => {
console.log(i);//打印出5个5
}, 0)
}
如果把var换成let,会打印出0,1,2,3,4
//var提升问题
console.log(f)
console.log(a)
var f;
var a = 123;
function f(){}
function a(){}
//请问f和a打印出来分别是什么?