ES6新語法之---函數擴展(7)

這節學習ES6中對函數新增的方法和屬性。html

1.新增函數的參數默認值app

參考S6系列第二篇:http://www.cnblogs.com/diweikang/p/8976854.html函數

2.新增了函數的rest參數學習

參考ES6系列第二篇:http://www.cnblogs.com/diweikang/p/8976854.htmlthis

3.length屬性url

  做用:獲取函數預期傳入的參數個數。spa

  指定默認值後,length屬性將返回沒有指定默認值參數的個數。.net

(function (a) {}).length // 1
    (function (a = 5) {}).length // 0
    (function (a, b, c = 5) {}).length // 2

  注意:若是設置了默認值的參數不是尾參數,length屬性也再也不計入後面的參數。prototype

(function (a = 0, b, c) {}).length // 0
    (function (a, b = 1, c) {}).length // 1

4.嚴格模式rest

  嚴格模式是ES5中新增語法的,限制指定的代碼在更嚴格的模式下執行。一般在腳本開頭或函數頭部添加"use strict"表達式來聲明。

  <1>ES5開始,函數內部能夠顯示聲明嚴格模式。

function doSomething(a, b) { 'use strict'; // ...
    }

  ES2016中規定,只要函數中使用了參數默認值、解構賦值、或者擴展運算符,函數內部就不容許顯示聲明嚴格模式,不然報錯。

// 參數默認值
    function doSomething(a, b = a) { 'use strict'; // code
 } // 解構賦值
    const doSomething = function ({a, b}) { 'use strict'; // code
 }; // 擴展運算符
    const doSomething = (...a) => { 'use strict'; // code
 }; const obj = { // 解構賦值
 doSomething({a, b}) { 'use strict'; // code
 } };

  規定緣由:函數內部聲明的嚴格模式,限制函數參數和函數體都必須是嚴格模式執行。只有執行函數體的時候才能知道函數是不是嚴格模式,可是函數時先執行函數參數,再執行函數體的。這就致使參數若是不遵照嚴格模式,函數體中又顯示聲明嚴格模式,函數進行就會報錯。

// 嚴格模式八進制使用0o前綴表示
    function doSomething(value = 070) { 'use strict'; return value; }

  上面函數執行就會報錯。

  如何規避這種限制:

    <1>、設定全局性的嚴格模式。

'use strict'; function doSomething(a, b = a) { // ...
    }

    <2>、把函數包裝在一個無參數的當即執行函數裏面。

const doSomething = (function () { 'use strict'; return function(value = 42) { return value; }; }());

5.name屬性

  ES6新增函數的name屬性,返回該函數的函數名。

  <1>將一個匿名函數賦值給一個變量,ES5的name屬性會返回空字符創,ES6的name屬性會返回實際的函數名稱。

var f = function () {}; // ES5
    f.name // ""
    // ES6
    f.name // "f"

  <2>將一個具名函數賦值給一個變量,ES5和ES6的name屬性都會返回這個具名函數的名稱。

const bar = function baz() {}; // ES5
    bar.name // "baz"
    // ES6
    bar.name // "baz"

  <3>構造函數返回的函數實例,name屬性值爲anonymous

(new Function).name // "anonymous"

  <4>將bind返回的函數,name屬性值會加上bound前綴。

function foo() {}; foo.bind({}).name // "bound foo"
 (function(){}).bind({}).name // "bound "

6.箭頭函數

  ES6容許使用"箭頭"(=>)定義函數。

  <1>箭頭函數須要一個參數

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>若是箭頭函數須要返回一個對象對象外面須要小括號括起來,不然會被當成代碼塊返回。

// 報錯
    let getTempItem = id => { id: id, name: "Temp" }; // 不報錯
    let getTempItem = id => ({ id: id, name: "Temp" });

  <5>若是箭頭函數只有一行語句,且不須要返回值,能夠採用下面的寫法。

let fn = () => void doesNotReturn();

  <6>箭頭函數與變量解構結合使用。

const full = ({ first, last }) => first + ' ' + last; // 等同於
    function full(person) { return person.first + ' ' + person.last; }
const numbers = (...nums) => nums; numbers(1, 2, 3, 4, 5) // [1,2,3,4,5]
 const headAndTail = (head, ...tail) => [head, tail]; headAndTail(1, 2, 3, 4, 5) // [1,[2,3,4,5]]

  <8>箭頭函數中的this對象。

  注意:箭頭函數中的this老是指向函數定義生效時所在的對象。

function foo() { setTimeout(() => { console.log('id:', this.id); }, 100); } var id = 21; foo.call({ id: 42 }); // id: 42

  上面代碼中,setTimeout的參數是一個箭頭函數,這個箭頭函數的定義生效是在foo函數生成時,而它的真正執行要等到 100 毫秒後。若是是普通函數,執行時this應該指向全局對象window,這時應該輸出21。箭頭函數致使this老是指向函數定義生效時所在的對象(本例是{id: 42}),因此輸出的是42

  再看一個例子:

function Timer() { this.s1 = 0; this.s2 = 0; // 箭頭函數
      setInterval(() => this.s1++, 1000); // 普通函數
      setInterval(function () { this.s2++; }, 1000); } var timer = new Timer(); setTimeout(() => console.log('s1: ', timer.s1), 3100); setTimeout(() => console.log('s2: ', timer.s2), 3100); // s1: 3
    // s2: 0

  分析:箭頭函數中的this指向箭頭函數定義生效時所在的對象,第一個定時器中的this指向timer對象,第二個定時器指向調用它的對象(全局對象),3100ms後s1更新了3次,而s2並無更新,因此結果是3和0。

  總結:箭頭函數沒有自身的this對象。

    1.函數體中this對象,定義時所在的對象,不是函數調用時所在對象。

    2.不能夠當構造函數,也就是不可使用new命令。

    3.不可使用arguments對象,該對象在箭頭函數體內不存在。

  <9>雙冒號運算符

  ES6中提出使用雙冒號(::)函數綁定的運算符,替代call、apply、bind調用。

  雙冒號左邊是一個對象,右邊是一個方法,表示將右邊的函數綁定到左邊的對象上。

 foo::bar; // 等同於
 bar.bind(foo); foo::bar(...arguments); // 等同於
 bar.apply(foo, arguments); const hasOwnProperty = Object.prototype.hasOwnProperty; function hasOwn(obj, key) { return obj::hasOwnProperty(key); }

  雙冒號左邊爲空,右邊是一個對象的方法,表示將函數綁定到這個對象上。

var method = obj::obj.foo; // 等同於
    var method = ::obj.foo; let log = ::console.log; // 等同於
    var log = console.log.bind(console);

總結:

  上面這些就是咱們在開發中,可能會用到的ES6中關於函數的擴展的屬性和方法,仍是須要多練習多理解。

相關文章
相關標籤/搜索