JS薛定谔的变量提升

953 阅读3分钟

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打印出来分别是什么?