ECMAScript6简介2

2017-03-16  本文已影响13人  我不叫奇奇

一. 字符串的一些扩展

  1. for...of遍历

    1. ES6为字符串添加了遍历器接口,似的字符串可以被for...of循环遍历

      for (let codePoint of 'foo') {
      console.log(codePoint)
      }
      // "f"
      // "o"
      // "o"

    2. 除了遍历字符串,这个遍历器最大的优点是可以识别大于0xFFFF的码点,传统的for循环无法识别这样的码点。

      var text = String.fromCodePoint(0x20BB7);

      for (let i = 0; i < text.length; i++) {
      console.log(text[i]);
      }
      // " "
      // " "

      for (let i of text) {
      console.log(i);
      }
      // "𠮷"

      ,字符串text只有一个字符,但是for循环会认为它包含两个字符(都不可打印),而for...of循环会正确识别出这一个字符。

  2. 查找字符串的三个新方法

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

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

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

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

  3. repeat()

 1) repeat方法返回一个新字符串,表示将原字符串重复n次

        'x'.repeat(3) // "xxx"
            'hello'.repeat(2) // "hellohello"
            'na'.repeat(0) // "

 2) 参数如果是小数,会被取整。

          'na'.repeat(2.9) // "nana"
  1. padStart(). padEnd()

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

      'x'.padStart(5, 'ab') // 'ababx'
      'x'.padStart(4, 'ab') // 'abax'
      
      'x'.padEnd(5, 'ab') // 'xabab'
      'x'.padEnd(4, 'ab') // 'xaba'
      
    2. 如果原字符串的长度,等于或大于指定的最小长度,则返回原字符串。

    3. 如果用来补全的字符串与原字符串,两者的长度之和超过了指定的最小长度,则会截去超出位数的补全字符串。

       'abc'.padStart(10, '0123456789')
        // '0123456abc'
      
    4. 如果省略第二个参数,默认使用空格补全长度。

    5. 用途

      a. padStart的常见用途是为数值补全指定位数。下面代码生成10位的数值字符串
      
        '1'.padStart(10, '0') // "0000000001"
        '12'.padStart(10, '0') // "0000000012"
        '123456'.padStart(10, '0') // "0000123456"
      
      b. 另一个用途是提示字符串格式。
      
        '12'.padStart(10, 'YYYY-MM-DD') // "YYYY-MM-12"
        '09-12'.padStart(10, 'YYYY-MM-DD') // "YYYY-09-12"
      
  2. 模板字符串

    1. 传统的JavaScript语言,输出模板通常是这样写的。

         $('#result').append(
          'There are <b>' + basket.count + '</b> ' +
          'items in your basket, ' +
          '<em>' + basket.onSale +
          '</em> are on sale!'
         );
      
    2. 上面这种写法相当繁琐不方便,ES6引入了模板字符串解决这个问题

      $('#result').append(There are <b>${basket.count}</b> items in your basket, <em>${basket.onSale}</em> are on sale!);

    3. 模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。

    4. 如果在模板字符串中需要使用反引号,则前面要用反斜杠转义。

    5. 如果使用模板字符串表示多行字符串,所有的空格和缩进都会被保留在输出之中,所有模板字符串的空格和换行,都是被保留的

    6. 模板字符串中嵌入变量,需要将变量名写在${}之中。

    7. 大括号内部可以放入任意的JavaScript表达式,可以进行运算,以及引用对象属性,也可以调用函数

    8. 如果需要引用模板字符串本身,在需要时执行,可以像下面这样写。

      // 写法一
      let str = 'return ' + 'Hello ${name}!';
      let func = new Function('name', str);
      func('Jack') // "Hello Jack!"

      // 写法二
      let str = '(name) => Hello ${name}!';
      let func = eval.call(null, str);
      func('Jack') // "Hello Jack!"

  3. 模板编译

  4. 通过模板字符串,生成正式模板的实例。

          var template = `
            <ul>
              <% for(var i=0; i < data.supplies.length; i++) { %>
                <li><%= data.supplies[i] %></li>
              <% } %>
            </ul>
          `;
    

上面代码在模板字符串之中,放置了一个常规模板。该模板使用<%...%>放置JavaScript代码,使用<%= ... %>输出JavaScript表达式

 2. 编译这个模板字符串

         function compile(template){
          var evalExpr = /<%=(.+?)%>/g;
          var expr = /<%([\s\S]+?)%>/g;

          template = template
            .replace(evalExpr, '`); \n  echo( $1 ); \n  echo(`')
            .replace(expr, '`); \n $1 \n  echo(`');

          template = 'echo(`' + template + '`);';

          var script =
          `(function parse(data){
            var output = "";

            function echo(html){
              output += html;
            }

            ${ template }

            return output;
          })`;

          return script;
        }

         var parse = eval(compile(template));

         div.innerHTML = parse({ supplies: [ "broom", "mop", "cleaner" ] });

         //   <ul>
         //     <li>broom</li>
         //     <li>mop</li>
         //     <li>cleaner</li>
         //   </ul>

二. 正则的扩展

  1. RegExp构造函数

    以前创建正则对象有两种方式

    var regex = new RegExp('xyz', 'i');
    var regex = /xyz/i;

    现在多了一种

    var regex = new RegExp(/xyz/, 'i');

  2. 字符串的正则方法

三. 数组的扩展

  1. Array.from

    1. 用于将两类对象转为真正的数组:类似数组的对象和可遍历的对象

      ES5的写法

         var arr1 = [].slice.call(arrayLike);
      

      ES6的写法

          let arr2 = Array.from(arrayLike);
      
    2. 实际应用中,常见的类似数组的对象是DOM操作返回的NodeList集合,以及函数内部的arguments对象。Array.from都可以将它们转为真正的数组。

          // NodeList对象
          let ps = document.querySelectorAll('p');
          Array.from(ps).forEach(function (p) {
            console.log(p);
          });
      
          // arguments对象
          function foo() {
            var args = Array.from(arguments);
            // ...
          }
      
    3. Array.from还可以接受第二个参数,作用类似与数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组

         Array.from(arrayLike, x => x * x);
          // 等同于
          Array.from(arrayLike).map(x => x * x);
      
          Array.from([1, 2, 3], (x) => x * x)
          // [1, 4, 9]
      
  2. Array.of()

    1. 用于将一组值,转换为数组

         Array.of(3, 11, 8) // [3,11,8]
          Array.of(3) // [3]
          Array.of(3).length // 1
      

      这个方法的主要目的,是弥补数组构造函数Array()的不足,因为参数个数的不同,会导致Array()的行为有差异

         Array() // []
          Array(3) // [, , ,]
          Array(3, 11, 8) // [3, 11, 8]
      
    2. Array.of基本上可以用来替代Array()或new Array(),并且不存在由于参数不同而导致的重载,他的行为非常统一,Array.of总是返回参数值组成的数组,如果没有参数,就返回一个空数组

  3. 数组实例的copyWithin()

    1. 数组实例的copyWithin方法,在当前数组内部,将指定位置的成员赋值到其他位置(会覆盖原有成员),然后返回当前数组,也就是说,使用这个方法,会修改当前数组

      Array.prototype.copyWithin(target, start = 0, end = this.length)

      target(必需):从该位置开始替换数据

      start(可选): 从该位置开始读取数据,默认为0,如果为负值,表示倒数

      end(可选):到该位置前停止读取数据,默认等于数组长度,如果为负值,表示倒数

      这三个参数都应该是数值,如果不是,会自动转为数值

         [1, 2, 3, 4, 5].copyWithin(0, 3)
          // [4, 5, 3, 4, 5]
      

      上面代码表示将从3号位直到数组结束的成员(4和5),复制到从0号位开始的位置,结果覆盖了原来的1和2。

  4. 数组实例的find()

    1. 数组实例的find方法,用于找出第一个符合条件的数组成员,所有数组成员依次执行该回调函数,直到找出第一个返回值为true的成员,然后返回该成员。乳沟没有符合条件的成员,则返回undefined

         [1, 4, -5, 10].find((n) => n < 0)
      // -5
      
  5. 数组实例的fill

    1. fill方法使用给定值,填充一个数组

      ['a', 'b', 'c'].fill(7)
      // [7, 7, 7]

      new Array(3).fill(7)
      // [7, 7, 7]

    2. fill方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置

      ['a', 'b', 'c'].fill(7, 1, 2)
      // ['a', 7, 'c']

      fill方法从1号位开始,向原数组填充7,到2号位之前结束。

  6. 数组实例的entries(),keys()和values()

    1)ES6提供三个新的方法——entries(),keys()和values()——用于遍历数组。它们都返回一个遍历器对象,可以用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"
    

    2)如果不使用for...of循环,可以手动调用遍历器对象的next方法,进行遍历。

  7. 数组实例的includes()

四. 函数的扩展

  1. 函数参数的默认值

    1. ES6 允许为函数的参数设置默认值,即直接写在参数定义的后面。

      function log(x, y = 'World') {
           console.log(x, y);
         }
      
         log('Hello') // Hello World
         log('Hello', 'China') // Hello China
         log('Hello', '') // Hello
      
    2. 参数变量是默认声明的,所以不能用let或const再次声明。

    3),定义了默认值的参数,应该是函数的尾参数。因为这样比较容易看出来,到底省略了哪些参数。如果非尾部的参数设置默认值,实际上这个参数是没法省略的。

    1. 函数的length属性

    指定了默认值以后,函数的length属性,将返回没有指定默认值的参数个数。也就是说,指定了默认值后,length属性将失真。

    1. 应用

      利用参数默认值,可以指定一个参数不得省略,如果省略就抛出一个错误

          function throwIfMissing() {
             throw new Error('Missing parameter');
           }
      
           function foo(mustBeProvided = throwIfMissing()) {
             return mustBeProvided;
           }
      
           foo()
           // Error: Missing parameter
      
  2. rest参数

    1. ES6引入了rest参数(形式为"...变量名"),用于获取函数的多余参数,这样就不需要使用arguments对象了,rest参数搭配的变量师一个数组,该变量将多余的参数放入数组中

      function add(...values) {
      let sum = 0;

      for (var val of values) {
      sum += val;
      }

      return sum;
      }

      add(2, 5, 3) // 10

    2. 下面是一个利用 rest 参数改写数组push方法的例子

      function push(array, ...items) {
      items.forEach(function(item) {
      array.push(item);
      console.log(item);
      });
      }

      var a = [];
      push(a, 1, 2, 3)

    3. rest 参数之后不能再有其他参数(即只能是最后一个参数)

  3. 扩展运算符

    1. 扩展运算符(spread)是三个点(...)将一个数组转为用逗号分隔的参数序列。

        console.log(...[1, 2, 3])
          // 1 2 3
      
          console.log(1, ...[2, 3, 4], 5)
          // 1 2 3 4 5
      
          [...document.querySelectorAll('div')]
          // [<div>, <div>, <div>]
      
    2. 运算符主要用于函数调用。

         function push(array, ...items) {
           array.push(...items);
          }
      
          function add(x, y) {
           return x + y;
          }
      
          var numbers = [4, 38];
          add(...numbers) // 42
      
    3. 替代数组的apply方法

      // ES5的写法
      function f(x, y, z) {
      // ...
      }
      var args = [0, 1, 2];
      f.apply(null, args);

      // ES6的写法
      function f(x, y, z) {
      // ...
      }
      var args = [0, 1, 2];
      f(...args);

    4. 扩展运算符的应用

      合并数组

      // ES5
      [1, 2].concat(more)
      // ES6
      [1, 2, ...more]
      
      var arr1 = ['a', 'b'];
      var arr2 = ['c'];
      var arr3 = ['d', 'e'];
      
      // ES5的合并数组
      arr1.concat(arr2, arr3);
      // [ 'a', 'b', 'c', 'd', 'e' ]
      
      // ES6的合并数组
      [...arr1, ...arr2, ...arr3]
      // [ 'a', 'b', 'c', 'd', 'e' ]
      
    5. 扩展运算符还可以将字符串转为真正的数组

          [...'hello']
       // [ "h", "e", "l", "l", "o" ]
      
    6. 何Iterator接口的对象,都可以用扩展运算符转为真正的数组。

        var nodeList = document.querySelectorAll('div');
      
       var array = [...nodeList];
      
  4. 箭头函数

    1. ES6允许使用“箭头”(=>)定义函数

        var f = v => v;
      
         ==>
      
       var f = function(v) {
            return v;
         };
      
    2. 如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分

        var f = () => 5;
          // 等同于
          var f = function () { return 5 };
      
          var sum = (num1, num2) => num1 + num2;
          // 等同于
          var sum = function(num1, num2) {
            return num1 + num2;
          };
      
    3. 如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return语句返回。

         var sum = (num1, num2) => { return num1 + num2; }
      
    4. 由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号。

         var getTempItem = id => ({ id: id, name: "Temp" });
      
    5. 箭头函数使得表达更加简洁。

      上面代码只用了两行,就定义了两个简单的工具函数。如果不用箭头函数,可能就要占用多行,而且还不如现在这样写醒目。

    6. 箭头函数的一个用处是简化回调函数

       // 正常函数写法
          [1,2,3].map(function (x) {
            return x * x;
          });
      
          // 箭头函数写法
          [1,2,3].map(x => x * x);
      
    7. 使用注意点

      a. 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

      b. 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。

      c. 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用Rest参数代替。

  5. 绑定this

五. 对象的扩展

  1. 属性的简洁表示法
 1) ES6允许直接写入变量和函数,作为对象的属性和方法

      var foo = 'bar';
      var baz = {foo};
      baz // {foo: "bar"}

 2) 方法也可以简写

          var o = {
              method() {
                return "Hello!";
              }
             };

 3) 实际例子

             var birth = '2000/01/01';

             var Person = {

              name: '张三',

              //等同于birth: birth
              birth,

              // 等同于hello: function ()...
              hello() { console.log('我的名字是', this.name); }

             };
  1. Object.assign()
 1) 用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。

           var target = { a: 1 };

             var source1 = { b: 2 };
             var source2 = { c: 3 };

             Object.assign(target, source1, source2);
             target // {a:1, b:2, c:3}

 2) Object.assign拷贝的属性是有限制的,只拷贝源对象的自身属性(不拷贝继承属性)

 3) 注意点

     a. Object.assign方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。

          var obj1 = {a: {b: 1}};
          var obj2 = Object.assign({}, obj1);

          obj1.a.b = 2;
          obj2.a.b // 2

     b. 对于这种嵌套的对象,一旦遇到同名属性,Object.assign的处理方法是替换,而不是添加。

 4) 常见用途
 
    a. 为对象添加属性

         class Point {
          constructor(x, y) {
            Object.assign(this, {x, y});
          }
         }

    b. 为对象添加方法

         Object.assign(SomeClass.prototype, {
          someMethod(arg1, arg2) {
            ···
          },
          anotherMethod() {
            ···
          }
        });

    c. 克隆对象

         function clone(origin) {
          return Object.assign({}, origin);
         }

    d. 合并多个对象

         const merge = (target, ...sources) => Object.assign(target, ...sources);
  1. 属性的遍历
 1) for...in

     循环遍历对象自身的和可继承的可枚举属性

 2) object.keys(obj)

     Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含Symbol属性)。
  1. Object.keys()/Object.values()/Object.entries()
 1) Object.keys()

    ES5 引入了Object.keys方法,返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名
上一篇下一篇

猜你喜欢

热点阅读