最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 深入了解ES6的let与var、const的区别

    正文概述 掘金(南蓝)   2021-01-03   452

    let与var、const的区别

    稍微熟悉前端,都应该回答出来,很经典的面试题

    let与var的区别

    let作用域不会被提升
    • 示例
    console.log(b)  // 报错
    let b = 1
    
    console.log(a)  //  undefined
    var a = 1
    
    • 原因

    js引擎遇到var声明,会把它的作用域提升到顶部,而遇到let或const会放到TDZ(Temporal Dead Zone,暂时性死区),访问TDZ的变量会触发运行时错误,只有执行变量声明的语句之后,变量才会从TDZ中取出。

    let重复声明会报错
    • 示例
    var a = 2
    var a = 22
    console.log(a) // 22
    
    let a = 2
    let a = 22
    console.log(a) // Identifier 'a' has already been declared
    
    • 原因

    因为let不允许在相同作用域内重复声明相同的变量,注意关键词 "相同作用域",下面的例子是没问题的

    let a = 2
    function f(){
      let a =3
      console.log(a)
    }
    f()
    
    let不绑定全局作用域
    • 示例
    let a = 1
    console.log(window.a) // undefined
    
    var a = 2
    console.log(window.a) // a
    
    • 原因

    暂没有想到

    let与const的区别

    const 一般用来声明常量,一旦声明一般类型,值就可以被修改,但是声明引用类型的值,值可以被修改,但是绑定不可以修改

    • 示例
    const a = 2;
    a = 3    // 可以
    
    const a = {name: "nanlan",age: 99}
    a.name = "xiaojuju"  // 可以
    a.sex = "female" // 可以
    a = { }  // 不可以,"a" is read-only
    a = {name:"nanlan”,age: 99,hobby: "coding"}  // 不可以,"a" is read-only
    
    const arr = [1,2,3,4]
    arr[1] = 88   // 可以
    arr.push(5)     // 可以
    arr.splice(0,2)   // 可以
    arr.pop()       //  可以
    arr = []        // 不可以,"arr" is read-only
    
    • 原因

    原始数据类型: undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)、Symbol

    细分的话,普通类型(String、Null、Undefined、Number、Boolean、Symbol)与引用类型(Function、Object、Array)存储的方式不一样。 请看下图(太丑请尽情吐槽)

    深入了解ES6的let与var、const的区别

    MDN截图 深入了解ES6的let与var、const的区别

    总结: 我理解的就是const声明就是一个值的只读引用。普通类型的地址也存放在栈内存中,引用类型在栈内存中存放了指向堆内存的地址,堆内存的值可以改变,栈内存的地址不可改变。

    更好的答案:

    Object.freeze

    冻结对象,如果对象里面嵌套了对象,则无效,目前想到的办法就是递归调用。比如

    // 代码1
    const foo = { a: "aaa", b: "bbb", c: "ccc"}
    Object.freeze(foo)
    foo.c = "ddd"
    console.log("foo",foo)  // { a: "aaa", b: "bbb", c: "ccc"}  // 不变
    
    
    // 代码2
    const foo = { a: "aaa", b: "bbb", c: "ccc", d:{e:"eee"} }
    Object.freeze(foo)
    foo.d.e ="ddee"
    console.log("foo",foo) // { a: "aaa", b: "bbb", c: "ccc", d:{ e:"ddee"} }  
    // 会变
    

    deepFreeze

    function deepFreeze(obj) {
      if (Object.prototype.toString.call(obj) !== "[object Object]") {
        throw new TypeError("Excepted Object,got " + typeof obj);
      }
    
      Object.keys(obj).forEach(function (name) {
        if (typeof obj[name] == "object" && obj[name] !== null)
          deepFreeze(obj[name]);
      });
      return Object.freeze(obj);
    }
    
    const foo = { a: "ddd", b: "bbb", c: "ccc", d: { e: "eee" } };
    deepFreeze(foo);
    // Object.freeze(foo)
    foo.d.e = "ddee";
    console.log(foo); // { a: "ddd", b: "bbb", c: "ccc", d: { e: "eee" } } 
    // 不变
    
    

    块级作用域

    一个经典的面试题

    // 代码1
    var funs = []
    for(var i=0;i<3;i++){
      funs[i] = function(){
          console.log(i)
      }
    }
    // funs[0]()  // 3
    
    
    // 代码2
    for(let i=0;i<3;i++){
      funs[i] = function(){
          console.log(i)
      }
    }
    // funs[0]()  // 0
    
    
    // 代码2的伪代码
    
    // 伪代码
    (let i = 0) {
        funcs[0] = function() {
            console.log(i)
        };
    }
    
    (let i = 1) {
        funcs[1] = function() {
            console.log(i)
        };
    }
    
    (let i = 2) {
        funcs[2] = function() {
            console.log(i)
        };
    };
    
    
    

    所以代码2的原因是因为存在块级作用域。即每次循环都会创建一个新的变量(按理来说,let声明的变量不可重复),其实循环的圆括号内会创建一个新的作用域,所以避免了let不可重复声明的特性,可以理解为模仿闭包来简化循环过程

    下面是来自阮老师的例子,先不看答案

    var tmp = new Date();
    function f() {
      console.log(tmp);
      if (false) {
        var tmp = 'hello world';  // 将这里换成let试试,思考下结果的区别和原因
      }
    }
    f(); 
    

    值得注意的是,在块级作用域中声明函数相当于是用var关键字声明,作用域会被提升到块级作用域的头部。猜猜下面的结果是多少

    function f() { console.log('I am outside!'); }
    (function () {
      var f = undefined;
      if (false) {
        function f() { console.log('I am inside!'); }
      }
      f();
    }());
    

    参照:

    ES6 系列之 let 和 const

    MDN const

    JavaScript 深入了解基本类型和引用类型的值

    let 和 const 命令

    「前端进阶」JS中的栈内存堆内存


    起源地下载网 » 深入了解ES6的let与var、const的区别

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元