zoukankan      html  css  js  c++  java
  • javaScript 变量提升 var let const,以及JS 的解析阶段和执行阶段

    我们先来看一道面试题,大家猜想一下,下面这段代码,打印出来的结果是什么

    var name = 'World!';
    (function () {
        if (typeof name === 'undefined') {
            var name = 'Jack';
            console.log('Goodbye ' + name);
        } else {
            console.log('Hello ' + name);
        }
    })(); 

    这里打印出来的结果为什么是 Goodbye Jack, 而不是Hello World呢。

    因为JS代码运行分为两个阶段:解析阶段和执行阶段

    解析阶段:找到所有的声明,包括函数声明和var声明,并把声明操作提升到它所在执行环境的顶部(全局或者函数内),而赋值和逻辑操作则会被留在原地等待代码执行。

                       并且,当它发现了函数名与函数名或者函数名与变量名冲突的时候,处理原则是:‘处理函数声明冲突时会覆盖,处理变量声明时冲突会忽略’。(后面再详解)

    经过解析阶段之后,我们的代码其实被解析成了这样:

    var name = 'World!';
    (function () {
            var name; // 对变量name的声明会被提升到函数的顶部,并且局部的变量name会覆盖全局的变量name
        if (typeof name === 'undefined') {
            name = 'Jack';
            console.log('Goodbye ' + name);
        } else {
            console.log('Hello ' + name);
        }
    })(); 

    执行阶段:赋值和逻辑操作就会被放在执行阶段。所以当我们在执行阶段时,由于name变量的声明被提升了,在if内判断typeof name的时候,赋值操作(即name='Jack')还未执行,所以  typeof name === 'undefined'  判断结果为true,打印出来的结果就是‘GoodBye Jack’。

    而在ES6中新规范中的 let,const 会不会执行变量提升呢? 我做了这么一个小实验

    (function () {
        console.log(i); // undefined
        var i = 'test const';
    })(); 
    (function () {
        console.log(i);  // ReferenceError: i is not defined
        let i = 0;
    })();
      
    (function () {
        console.log(i); // ReferenceError: i is not defined
        const i = 'test const';
    })();

    可以看到 let 和const 声明的变量是不会被提升的,这也是为什么一开始的时候我把字体标红:函数声明和var声明会被提升。

    那我们接着说一下函数声明的提升

    定义函数有两种非常常见的方式

    function A(){   // 函数声明
        alert('A');
    }
    
    var B = function(){  // 函数表达式
        alert('B')
    }

    对于用函数声明的方式定义的函数,我们可以在函数之前调用,这就是因为JS在解析阶段把整个函数提升到了全局环境的最上面,

    而对于函数表达式方式定义的函数,我们在函数之前调用的话,会得到undefined的结果,因为var 声明的变量被提升了,但是赋值操作还没有执行

    我们看一下执行结果

    console.log(A); // ƒ A(){ alert('A'); }
    function A(){   
        alert('A');
    }
    
    console.log(B);  // undefined
    var B = function(){  
        alert('B')
    }
    

      

    关于js的解析和执行阶段的补充详解,将在下一篇博客中讲解

  • 相关阅读:
    Codeforces Round #646 (Div. 2)【B. Subsequence Hate题解】
    关于MyBatis常见映射异常
    SQL语句汇总(终篇)—— 表联接与联接查询【转载自https://www.cnblogs.com/ghost-xyx/p/3813688.html】
    SQL语句汇总(二)——数据修改、数据查询【转载自https://www.cnblogs.com/ghost-xyx/p/3798362.html】
    浮动元素引起的问题和解决办法
    PHP 神奇的sprintf函数
    关于this,作用域,属性,原型链的一个小练习
    for...of 与 for...in 区别
    ES6 Promise对象then方法链式调用
    ES6通过WeakMap解决内存泄漏问题
  • 原文地址:https://www.cnblogs.com/daisygogogo/p/8508320.html
Copyright © 2011-2022 走看看