ECMAScript6簡介2

一. 字符串的一些擴展

  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)屬性的鍵名
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 第5章 引用類型(返回首頁) 本章內容 使用對象 創建并操作數組 理解基本的JavaScript類型 使用基本類型...
    大學一百閱讀 3,270評論 0 4
  • Javascript有很多數組的方法,有的人有W3C的API,還可以去MDN上去找,但是我覺得API上說的不全,M...
    頑皮的雪狐七七閱讀 4,220評論 0 6
  • 第1章 認識JS JavaScript能做什么?1.增強頁面動態效果(如:下拉菜單、圖片輪播、信息滾動等)2.實現...
    mo默22閱讀 1,338評論 0 5
  • 想要落筆,卻又不知該如何提起,想說的話太多,又害怕不能用華麗的語言,完美的表達感情。 我們之間,有太多的矛盾和牽絆...
    半夏畏生姜閱讀 266評論 0 2
  • 生活壓力大!必須使自己成為有錢人?要比同事掙得多,才能說明自己工作能力強?當然,無可厚非!但是,作為“青年人才...
    qianli閱讀 455評論 0 4