• 481 let、const和var的区别


    1.let和const不存在变量提升机制

    创建变量的六种方式中:var/function有变量提升,而let/const/class/import都不存在这个机制


    2.var允许重复声明,而let是不允许的

    在相同的作用域中(或执行上下文中)

    • 如果使用var/function关键词声明变量并且重复声明,是不会有影响的(声明第一次之后,之后再遇到就不再重复声明了)
    • 但是使用let/const就不行,浏览器会校验当前作用域中是否已经存在这个变量了,如果已经存在了,则再次基于let等重新声明就会报错
    // => 在浏览器开辟栈内存供代码自上而下执行之前,不仅有变量提升的操作,还有很多其它的操作 => “词法解析”或者“词法检测”:就是检测当前即将要执行的代码是否会出现“语法错误 SyntaxError”,如果出现错误,代码将不会再执行(第一行都不会执行)
    console.log(1); // => 这行代码就已经不会再被执行了
    let a = 12;
    console.log(a);
    let a = 13;  // => Uncaught SyntaxError: Identifier 'a' has already been declared
    console.log(a);
    
    // => 所谓重复是:不管之前通过什么办法,只要当前栈内存中存在了这个变量,我们使用let/const等重复再声明这个变量就是语法错误
    console.log(a);
    var a = 12;
    let a = 13; // => Uncaught SyntaxError: Identifier 'a' has already been declared
    console.log(a);
    

    3.let能解决typeof检测时出现的暂时性死区问题(LET比VAR更严谨)

    http://es6.ruanyifeng.com/#docs/let

    console.log(a); // => Uncaught ReferenceError: a is not defined
    
    // 在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”
    console.log(typeof a); // => "undefined"  这是浏览器的BUG,本应该是报错的,因为没有a(暂时性死区)
    
    console.log(typeof a); // => Uncaught ReferenceError: Cannot access 'a' before initialization
    let a;
    

    if判断中的变量提升

    // [PROPERTY] in [OBJECT] 验证当前属性是否属于这个对象   hasOwnProperty?
    let obj = {
    	name: '吴振宇',
    	age: 21,
    	GF: null
    };
    console.log("name" in obj); //  =>  TRUE  
    console.log("GF" in obj); //  =>  TRUE  
    console.log("BF" in obj); //  =>  FALSE
    
    
    
    // -----------------------------------------------------
    
    
    /*
     * 全局作用域
     *   1.变量提升  
     *     不管条件是否成立都要进行变量提升
     *     var a;  //  =>  创建一个全局变量a    =>  window.a
     *   2.代码执行
     */
    console.log(a); //  =>  undefined
    if (!('a' in window)) { //  =>  'a' in window    =>  TRUE
    	var a = 13;
    }
    console.log(a); //  =>  undefined
    
    
    // 变体
    console.log(a); // 报错
    if (!('a' in window)) { 
        let a = 13; // a 是块级作用域的变量,外面不能使用 
        console.log(a) // 13
    }
    console.log(a); // 报错
    
    
    
    // -----------------------------------------------------
    
    
    
    /*
     * 全局作用域
     *   1.变量提升  
     *     但是做函数的有特殊性:在老版本浏览器中,确实不论条件是否成立,函数也是提前声明或者定义的,但是新版本浏览器中,为了兼容ES6严谨的语法规范,条件中的函数在变量提升阶段只能提前声明,不能提前定义
     *     function fn;
     *   2.代码执行
     */
    // 这个不作为重点
    console.log(fn); //  =>  undefined
    // fn(); //  =>  Uncaught TypeError: fn is not a function
    if ('fn' in window) { //  =>  TRUE
    	// 条件成立,进来后的第一件事是给FN赋值,然后在代码执行
    	fn(); //  =>  "哈哈哈"
    	function fn() {
    		console.log('哈哈哈');
    	}
    }
    fn(); //  =>  "哈哈哈"
    
    
    
    
    // -----------------------------------------------------
    
    
    
    /*
     * 全局作用域
     *   1.变量提升 
     *   2.代码执行
     */
    f = function () {return true;}  //  =>  window.f=...
    g = function () {return false;}
    ~function () {
    	/*
    	 * 函数执行会形成一个私有作用域
    	 *   1.变量提升  function g,只声明,不赋值,默认值是undefined
    	 *   2.代码执行
    	 */
        if (g() && [] == ![]) { //  =>  Uncaught TypeError: g is not a function
            f = function () {return false;}
            function g() {return true;}
        }
    }();
    console.log(f());
    console.log(g());
    
    
    // --------------------------------
    
    
    //   =>   自执行函数:前面加的()或者!、-、~、+只有一个目的,让语法符合而已
    //   =>   自执行函数本身不进行变量提升(没名字)
    (function(n){})(10);
    ~function(n){}(10);
    -function(n){}(10);
    !function(n){}(10);
    +function(n){}(10);
    
  • 相关阅读:
    TSQL Beginners Challenge 1
    SQL拾遗
    简易实体生成方式
    CTE-递归[2]
    编号处理
    行列转换/横转竖
    OUTPUT、Merge语句的使用
    关于SQL IO的一些资料
    对左值(lvalue)和右值(rvalue)的两种理解方式
    跨平台判断64位和32位开发的一些宏定义
  • 原文地址:https://www.cnblogs.com/jianjie/p/13192945.html
Copyright © 2020-2023  润新知