美文网首页
ES6/7/8新特性总结

ES6/7/8新特性总结

作者: BULL_DEBUG | 来源:发表于2018-10-19 10:40 被阅读45次

    一、变量let、const:

    var存在的问题:1、重复声明;2、函数级

    经典案例:

     <body>
      <input type="button" value="1">
      <input type="button" value="2">
      <input type="button" value="3">
    </body>
    <script>
         window.onload = function () {
          //var aBtns = document.getElementsByTagName('input');
          // 点击每个按钮都弹出“3”
          // for (var i = 0, len = aBtns.length; i < len; i ++) {
          //   aBtns[i].onclick = function () {
          //     alert(i) 
          //   }
          // }
          // 闭包处理点击分别弹出“0、1、2”
          // for (var i = 0, len = aBtns.length; i < len; i ++) {
          //   (function(i) {
          //     aBtns[i].onclick = function () {
          //       alert(i) 
          //     }
          //   })(i);
          // }
          // let 分别弹出“0、1、2”
          // for (let i = 0, len = aBtns.length; i < len; i ++) {
          //   aBtns[i].onclick = function () {
          //     alert(i) 
          //   }
          // }
        }
    </script>
    

    let : 不能重复声明、块级、变量
    const: 不能重复声明、块级、常量

    二、箭头函数=>

    1.方便,简写规则:

    (1)如果只有一个参数,()可以省
    (2)如果只有一个return,{}也可以省
    

    2.修正this

    this相对正常点,指向问题、“箭头函数”的this,总是指向定义时所在的对象,而不是运行时所在的对象。
    

    三、参数扩展:...

    例子:

    function show(a, b, ...arg) {
          console.log(a);// 1
          console.log(b); // 2
          console.log(arg); // [3,4,5,6,7,8,89]
        }
    show(1, 2, 3, 4, 5, 6, 7, 8, 89);
    
    let arr = [12, 5, 8];
    let arr2 = [...arr, ...arr];
    console.log(arr2); // [12, 5, 8, 12, 5, 8]
    

    //解构 可以是嵌套数组、对象

        let [a, b, c] = [1, 2, 3];
    

    四、字符串

    传统上,JavaScript 只有indexOf方法,可以用来确定一个字符串是否包含在另一个字符串中。ES6 又提供了三种新方法。

    includes():返回布尔值,表示是否找到了参数字符串。
    startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。
    endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。

    let s = 'Hello world!';
    
    s.startsWith('Hello') // true
    s.endsWith('!') // true
    s.includes('o') // true
    

    这三个方法都支持第二个参数,表示开始搜索的位置。

    let s = 'Hello world!';
    
    s.startsWith('world', 6) // true
    s.endsWith('Hello', 5) // true
    s.includes('Hello', 6) // false
    

    上面代码表示,使用第二个参数n时,endsWith的行为与其他两个方法有所不同。它针对前n个字符,而其他两个方法针对从第n个位置直到字符串结束

    ES2017 引入了字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。padStart()用于头部补全,padEnd()用于尾部补全。

    'x'.padStart(5, 'ab') // 'ababx'
    'x'.padStart(4, 'ab') // 'abax'
    
    'x'.padEnd(5, 'ab') // 'xabab'
    'x'.padEnd(4, 'ab') // 'xaba'
    

    五、数组

    1、map 映射 一个对一个

    let arr = [1, 5, 7];
        let result = arr.map(function(item) {
          return item * 2;
        })
    // let result=arr.map(item=>item*2); // 简写
        alert(result);  // 2,10,14
    
     let score = [30, 60, 100, 10, 80];
        let result  = score.map(item => item >= 60? '及格': '不及格');
        console.log(score); // [30, 60, 100, 10, 80]
        console.log(result) // ["不及格", "及格", "及格", "不及格", "及格"]
    

    2、reduce 总汇:一堆 -> 一个(算总数、平均数等)

    参数说明:*第一个参数是上次reduce函数运算的结果
    *第二个参数是下次要参与运算的元素

    let arr = [12, 69, 180, 8763];
        let result = arr.reduce(function (tmp, item, index) {
          console.log(`${tmp},${item},${index}`);// 12,69,1    81,180,2    261,8763,3
          return tmp + item;
        });
        console.log(result); // 9024
    

    3、filter 过滤: 一堆-> 剩下的

     let arr = [
          {title: '男士衬衫', price: 75},
          {title: '女士包', price: 57842},
          {title: '男士包', price: 65},
          {title: '女士鞋', price: 27531}
        ];
        let result = arr.filter(item => item.price > 10000)
        console.log(result);// [{title: '女士包', price: 57842},{title: '女士鞋', price: 27531}]
    

    4、forEach 循环(迭代)

     let arr = [12, 5, 8];
        arr.forEach((item, index) => {
          if (index > 1) {
            // break; // 报错 不能用在function中
            // continue; // 报错 不能用在function中
            //return; // 0:12 1:5
          }
          console.log(`${index}:${item}`);// 0:12 1:5 2:8
        });
    

    5、includes数组是否包含某个东西

    该方法的第二个参数表示搜索的起始位置,默认为0。如果第二个参数为负数,则表示倒数的位置,如果这时它大于数组长度(比如第二个参数为-4,但数组长度为3),则会重置为从0开始。

    [1, 2, 3].includes(3, 3);  // false
    [1, 2, 3].includes(3, -1); // true
    

    6、 keys/values/entries

    它们都返回一个遍历器对象,可以用for...of循环进行遍历,唯一的区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历。

    for (let index of ['a', 'b'].keys()) {
      console.log(index);
    }
    // 0
    // 1
    
    for (let elem of ['a', 'b'].values()) {
      console.log(elem);
    }
    // 'a'
    // 'b'
    
    for (let [index, elem] of ['a', 'b'].entries()) {
      console.log(index, elem);
    }
    // 0 "a"
    // 1 "b"
    

    五、Promise(封装异步操作);

    // 1、基本用法
       let promise = new Promise((resolve, reject) => {
          $.ajax({
            url: 'url',
            dataType: 'json',
            success(res) {
              resolve(res);
            },
            error(err) {
              reject(err);
            }
          })
        })
        promise.then(res => {
          console.log(res); // 成功
        }, err => {
          console.log(err);// 失败
        })
    //2、 Promise.all,在一个接口中用到另一个接口中的数据
        Promise.all([
          $.ajax({url: 'url', dataType: 'json'}),
          $.ajax({url: 'url', dataType: 'json'})
        ]).then(results => {
          let [data1, data2] = results;
          console.log(data1, data2);
        }, () => {
          alert('失败了');
        });
    

    六、generator生成器 yield表达式;

     function* show(num1, num2) {
          console.log(`${num1}, ${num2}`); // 6,2
          let n1 = num1 + num2;
          let a = yield n1; 
          console.log(a); // 2
          let n2 = num1 - num2;
          let b = yield n2;
          console.log(b) // 3
          let n = n1 * n2;
          return n;
        }
        let gen = show(6, 2);
        console.log(gen.next(1)); // {value: 8, done: false}
        console.log(gen.next(2));  // {value: 4, done: false}
        console.log(gen.next(3)); // {value: 32, done: true}
        console.log(gen.next(4)); // {value: undefined, done: true}
        
        function *show() {
          yield $.ajax({url: 'url', dataType: 'json'});    
          return $.ajax({url: 'url', dataType: 'json'})
        }
        let genObj = show();
        console.log(genObj.next()); // {value: {…}, done: false}
        console.log(genObj.next()); // {value: {…}, done: true}
    

    七、async await

    与generator对比:1.不依赖于外部的runner了——统一、性能2.可以用箭头函数;

    八、面向对象 类 Class

     /* 类Class */
        // 先看 原型-面向对象
        // 定义一个用户类
        function User (name, phone) { 
          this.name = name || 'user';  // 属性
          this.phone = phone || '000'; // 属性
          this.showName = function () {
            console.log(`姓名:${this.name}`);
          }
        }
        User.prototype.showUserInfo = function (id) {
          console.log(`ID:${id}/姓名:${this.name}/手机号:${this.phone}`);
        }
        let user = new User('小明', '110');
        console.log(user);
        user.showName();
        user.showUserInfo('666');
        // 定义一个vip用户子类
        function VipUser(name, phone, level) {
          User.call(this, name, phone, level);
          this.level = level;
        }
        VipUser.prototype = new User(); // 将父级实例作为子类的原型
        VipUser.prototype.constructor = VipUser; // 需要修复构造函数指向
    
        VipUser.prototype.showVipInfo = function() { // 箭头函数会造成this指向问题
          console.log(`姓名:${this.name}/会员等级:${this.level}颗星/手机号:${this.phone}`)
        }
        let v1 = new VipUser ('老王', '12345678', '10')
        console.log(v1);
        v1.showUserInfo(123);
        v1.showVipInfo();
    
    //对比
    // es6 写法
        class User {
          constructor(name, phone) {
            this.name = name || 'user';  // 属性
            this.phone = phone || '000'; // 属性
          }
          showName () {
            console.log(`姓名:${this.name}`);
            // this.showPhone(); 
            // User.showPhone(this.phone); 
          }
          static showPhone(phone) {  // 只能内部使用,不能通过this/实例化方法调用
            // console.log(`手机号:${this.phone}`);
            console.log(`手机号:${phone}`);
          }
          showUserInfo (id) {
            console.log(`ID:${id}/姓名:${this.name}/手机号:${this.phone}`);
          }
        }
        let user = new User('小明', '110');
        console.log(user);
        user.showName();
        // user.showPhone();
        user.showUserInfo('666');
        class VipUser extends User {
          constructor(name, phone, level) {
            super(name, phone);
            this.level = level;
          }
          showVipInfo () { 
            console.log(`姓名:${this.name}/会员等级:${this.level}颗星/手机号:${this.phone}`)
          }
        }
        let v1 = new VipUser ('老王', '12345678', '10')
        console.log(v1);
        v1.showUserInfo(123);
        v1.showVipInfo();
    

    九、JSON

      JSON.stringify({a:12,b:5})  =>  '{"a":12,"b":5}' // 从一个对象中解析出字符串
      JSON.parse('{"a":12,"b":5}')=>  {a:12,b:5} // 从一个字符串中解析出JSON对象
    

    十、Symbol

    ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,前六种是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。作用:作为对象属性的唯一标识符,防止对象属性冲突发生。

      // let a = Symbol();
        // let b = Symbol();
        // console.log(a === b); // false
        // console.log(typeof(a)); // symbol
    
    // let obj = {};
        // let isOk = Symbol();
        // obj[isOk] = 'ok';
        // console.log(obj[isOk]);   // ok
        // console.log(obj.isOk);   // undefined  不能用点
    
       //Symbol.for会根据给定的键 key,来从运行时的 symbol 注册表中找到对应的 symbol,
        //如果找到了,则返回它,否则,新建一个与该键关联的 symbol,并放入全局 symbol 注册表中。
        //  let sym = Symbol('abc');
        //  let sym1 = Symbol.for('abc');
        //  let sym2 = Symbol.for('abc');
        //  console.log(sym === sym1); // false
        //  console.log(sym1 === sym2);// true
    

    十一、Iterator

    JavaScript 原有的表示“集合”的数据结构,主要是数组(Array)和对象(Object),ES6 又添加了Map和Set。这样就有了四种数据集合,用户还可以组合使用它们,定义自己的数据结构,比如数组的成员是Map,Map的成员是对象。这样就需要一种统一的接口机制,来处理所有不同的数据结构。

    遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。

    Iterator 的作用有三个:一是为各种数据结构,提供一个统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是 ES6 创造了一种新的遍历命令for...of循环,Iterator 接口主要供for...of消费。

    Iterator 的遍历过程是这样的。
    (1)创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。
    (2)第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。
    (3)第二次调用指针对象的next方法,指针就指向数据结构的第二个成员。
    (4)不断调用指针对象的next方法,直到它指向数据结构的结束位置。

    每一次调用next方法,都会返回数据结构的当前成员的信息。具体来说,就是返回一个包含value和done两个属性的对象。其中,value属性是当前成员的值,done属性是一个布尔值,表示遍历是否结束。

    for...of...不能循环对象是因为

    Iterator 接口的目的,就是为所有数据结构,提供了一种统一的访问机制,即for...of循环(详见下文)。当使用for...of循环遍历某种数据结构时,该循环会自动去寻找 Iterator 接口。

    原生具备 Iterator 接口的数据结构如下。
    Array
    Map
    Set
    String
    TypedArray
    函数的 arguments 对象
    NodeList 对象

    没有提供Object的数据机构接口

    十二、Set 和 Map 数据结构

    ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。Set 本身是一个构造函数,用来生成 Set 数据结构。

        let a = new Set([1, 2, 3]);
        let b = new Set([5, 3, 2]);
        // 并集
        let union = new Set([...a, ...b]);
        console.log(union);// Set {1, 2, 3, 4}
        // 交集
        let intersect = new Set([...a].filter(x => b.has(x)));
        console.log(intersect)// set {2, 3}
    

    JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。

    const data = {};
    const element = document.getElementById('myDiv');
    
    data[element] = 'metadata';
    data['[object HTMLDivElement]'] // "metadata"
    

    上面代码原意是将一个 DOM 节点作为对象data的键,但是由于对象只接受字符串作为键名,所以element被自动转为字符串[object HTMLDivElement]。

    为了解决这个问题,ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。

    const m = new Map();
        const o = {p: 'Hello World'};
        m.set(o, 'content')
        console.log(m); // Map(1) {{…} => "content"}
        console.log(m.get(o)); // "content"
        console.log(m.has(o)); // true
        m.delete(o);
        console.log(m.has(o)) // false
    

    上面代码使用 Map 结构的set方法,将对象o当作m的一个键,然后又使用get方法读取这个键,接着使用delete方法删除了这个键。

    相关文章

      网友评论

          本文标题:ES6/7/8新特性总结

          本文链接:https://www.haomeiwen.com/subject/letyzftx.html