跟着coderwhy学习JavaScript高级(十四)

280 阅读4分钟

ES6

字面量增强

ES6中对 对象字面量 进行了增强,称之为 Enhanced object literals(增强对象字面量)。

  • 属性的简写:Property Shorthand
  • 方法的简写:Method Shorthand
  • 计算属性名:Computed Property Names
    // 1.属性的简写
    var obj = {
        name: name
        age: age
    }
    // 增强后
    var obj = {
        name,
        age
    }
    
    // 2.方法的简写
    var obj = {
        foo: function() {}
    }
    // 增强后
    var obj = {
        foo() {},
    }
    
    // 3.计算属性名
    var name = "test"; 
    var obj = {}
    obj[name] = "haha"; //如果key是一个变量 不能用.的方式 要使用[]
    // 增强后
    var obj = {
      [name]: "haha"
    }

解构

ES6中新增了一个从数组或对象中方便获取数据的方法,称之为解构Destructuring

数组解构

    var names = ["a", "b", "c"];
    var ages = [1, 2, 3, 4, 5];

    // 取出数组中某一个
    var [item1, item2, item3] = names;

    // 解构出后面两个元素
    var [, item2, item3] = names

    // 解构出第一个元素,后面的元素放到一个新数组中
    var [itemx, ...newNames] = names

    // 解构默认值
    var [item1, item2, item3, item4 = "d"] = names
    console.log(item4)
    
    // 合并两个数组
    var arr = [...names, ...ages]

对象解构

    var obj = {
      name: "why",
      age: 18,
      height: 1.88
    };

    var obj1 = {
      name: "zhangsan",
      address: "深圳"
    }


    // 对象解构
    var { name, age, height } = obj;

    // // 解构出某个key,后面的key放到一个新对象中
    var { age, ...newObj } = obj;

    // // 解构出某个key 并且重新命名
    var { name, age: newAge, height } = obj;

    // 不用delete 如何删除 对象的某个属性? delete obj.a
    var { name, ...rest } = obj // 删除了a , c
    obj = rest;
    
    // 合并两个对象 相同的属性会被覆盖
    var obj2 = {...obj, ...obj1}
    

var/let/const

  • var
    • 没有块级作用域,是弱类型,支持变量提升。
    • 可以重复声明,没有报错和警告
    • ES5中只有全局作用域和函数作用域,大部分人会采用闭包来解决ES5的问题
  • let
    • 只有块级作用域 window无法访问
    • 不存在变量提升(解析阶段会被创建出来,但是不能被访问)
    • 存在暂时性死区(TDZ)
      //"暂时性死区"也意味着**typeof**不再是一个百分之百安全的操作。
      //在没有**let**之前,**typeof**是百分百安全的,现在这一点不成立了.
      typeof x; //ReferenceError: a is not defined.
      let x; 
      
    • 不允许重复声明
  • const
    • 只有块级作用域 window无法访问
    • 不存在变量提升(解析阶段会被创建出来,但是不能被访问)
    • 存在暂时性死区(TDZ)
    • 不允许重复声明
    • 声明时必须赋值,且后续不允许修改,如果是对象,对象的属性可以被修改。
  • 实际开发如何选择

首先排除varletconst之间做选择,建议优先使用const,尤其是在全局环境,不应该设置变量,只应设置常量。

一个是const可以提醒阅读程序的人,这个变量不应该改变;另一个是const比较符合函数式编程思想,运算不改变值,只是新建值,而且这样也有利于将来的分布式运算;最后一个原因是 JavaScript 编译器会对const进行优化,所以多使用const,有利于提高程序的运行效率,也就是说letconst的本质区别,其实是编译器内部的处理不同.

作用域

在ES6之前,只存在全局作用域和函数作用域。

    var text = "全局作用域";
    
    function foo() {
        var bar = "函数作用域,只有在这个函数才能访问"
    }

在ES6的时候有了块级作用域

    {
        var x = 123;
        let y = 456;
        const z = 789;
    }
    // 只有x 能正常被打印 
    console.log(x,y,z);

在ES6中,块级作用域对于var是没有作用的,var只有函数作用域和全局作用域。let、const存在块级作用域、函数作用域、全局作用域。块级作用域对于let、const、function、class等等一些是有效的。

    {
        function test() {
            console.log("测试块级作用域是否有效")
        }
        class Person{}
    }
    
    test(); // 能够正常调用函数,为什么呢?
    let p = new Person(); //Person is not defined
  • 上面说块级作用域对于function有效,那为什么在块级作用域之外能够调用函数呢?

不同浏览器有不同的实现(大部分浏览器为了兼容以前的代码),让我们的function是没有块级作用域的。但是在标准中,块级作用域对于function是存在的。但是如果有某一个浏览器 只支持ES6及以上的代码,这个时候test函数是访问不到的。

  • 块级作用域的补充
    const names = [1,2,3,4,5]
    
    // 这里是不能 使用const的 虽然const是块级作用域
    // 但是每次在块级作用域里面都在尝试修改 i ---> i++
    for(const i = 0; i < names.length; i++){
        console.log(names[i]);
    }
    
    // {
    //   i = 0;
    //   const i = i;
    // }
    
    // {
    //   i++;
    //   const i = i;  // const是没法被修改的,const初始化也必须要有值
    //   console.log(names[i]);
    // }

    // {
    //   i++;
    //   const i = i;  
    //   console.log(names[i]);
    // }
    
    // ...
    
    
    // for ... of 遍历可迭代对象
    // 这里是可以使用 const的
    for(const item of names) {
        console.log(item);
    }
    
    // 块级作用域
    // {
    //   const item = 1;
    //   console.log(item);
    // }

    // {
    //   const item = 2;
    //   console.log(item);
    // }
    
    ///.....