js中的箭頭函數


 箭頭函數是ES6標准中新增的一種函數,在詳細的討論箭頭函數之前,我們先來看看函數的四種定義方式

  函數的四種定義方式

  1、函數聲明的方式(常用)

function sum (num1,num2) {
      return num1 + num2;
 }

  注意函數定義最后沒有加分號。必須有名字,會函數提升,在預解析階段就已經創建,聲明前后都可以調用。

  2、函數表達式的方式

let sum = function(num1,num2) {
      return num1 + num2;
};

  一種變量賦值,函表達式可以沒有名字(匿名函數),沒有函數提升。函數表達式創建方式和函數聲明幾乎是等價的,這里代碼定義了一個變量sum並將其初始化為一個函數,這個函數可以通過sum來引用。注意這里函數末尾是有分號的,與任何變量初始化語句一樣。

  3、箭頭函數的方式

   //多個參數需要括號
    let sum = (num1,num2) => {
        return num1 + num2;
    };
    //以下兩種寫法都有效,只有一個參數可以不寫括號
    let double = (x) => { return 2 * x };
    let double = x => { return 2 * x };
    //沒有參數需要括號
    let getRandom = () => { return Math.random() };

     注意:箭頭函數在參數和箭頭之間不能換行,但是,可以通過在 ‘=>’ 之后換行,或者用 ‘( )’、'{ }'來實現換行

  任何可以使用函數表達式的地方,都可以使用箭頭函數。箭頭函數語法簡單,非常適合嵌入函數的場景。

   let ints = [1,2,3];
   console.log(ints.map(function (i){
        return i + 1
   }));//[2,3,4]
   console.log(ints.map(i => {return i + 1 }));//[2,3,4]
    //map()方法定義在JavaScript的Array中,它返回一個新的數組,數組中的元素為原始數組調用函數處理后的值。

  4、構造函數的方式(不推薦)

let sum = new Function("num1","num2","return num1 + num2");

  不推薦使用這種語法定義,因為這段代碼會被解釋兩次:第一次是把它作為常規ES代碼,第二次是解釋傳給構造函數的字符串。這顯然會影響性能。不過,把函數想象為對象,把函數名想象為指針這很重要。而上面的語法很好地詮釋了這個概念。

 

  箭頭函數中的this

  箭頭函數不綁定this, 它會捕獲其所在(即定義的位置)上下文的this值, 作為自己的this值,即箭頭函數內部的this是詞法作用域,由上下文確定

  在箭頭函數出現之前,每一個新函數根據它是被如何調用的來定義這個函數的this值:

  • 如果該函數是一個構造函數,this指針指向一個新的對象
  • 在嚴格模式下的函數調用下,this指向undefined
  • 如果該函數是一個對象的方法,則它的this指針指向這個對象
  • 等等

  由於 箭頭函數沒有自己的this指針,通過 call() 或 apply() 方法調用一個函數時,只能傳遞參數

var adder = {
  base : 1,

  add : function(a) {
    var f = v => v + this.base;
    return f(a);
  },

  addThruCall: function(a) {
    var f = v => v + this.base;
    var b = {
      base : 2
    };

    return f.call(b, a);
  }
};

console.log(adder.add(1));         // 輸出 2
console.log(adder.addThruCall(1)); // 仍然輸出 2

 

  接下來我們來看一個箭頭函數應用的例子:我們想每隔一秒輸出this.age的值加1

  function Person() {
        // Person() 構造函數定義 `this`作為它自己的實例.
        this.age = 0;

        setInterval(function add() {
            // 在非嚴格模式, add()函數定義 `this`作為全局對象,
            // 與在 Person()構造函數中定義的 `this`並不相同.
            this.age++;
            console.log(this.age);
        }, 1000);
    }
    var p = new Person();

 

  但是你會發現,每隔一秒都會有一個NaN打印出來,而不是累加的數字。到底哪里錯了呢? 實際上setInterval里面的this綁定到全局對象window,而window.age未定義,那么怎么解決這一問題呢?

  在ECMAScript 3/5中,通過將this值分配給封閉的變量,可以解決this問題。

  function Person() {
        var that = this;
        that.age = 0;

        setInterval(function add() {
            that.age++;// 回調引用的是`that`變量, 其值是預期的對象.
            console.log(that.age);
        }, 1000);
    }
    var p = new Person();

 

  使用箭頭函數解決,箭頭函數不會創建自己的this,它只會從自己的作用域鏈的上一層繼承this。因此,在下面的代碼中,傳遞給setInterval的函數內的this與封閉函數中的this值相同:

  function Person() {
        this.age = 0;

        setInterval(() => {
            this.age++;
            console.log(this.age);
        }, 1000);
    }
    var p = new Person();

 

  箭頭函數不綁定arguments

  箭頭函數不綁定arguments對象。

    function foo() {
        console.log(arguments[0]);
    }
    foo(5);//5

    let bar = () => {
        console.log(arguments[0]);
    }
    bar(5)//arguments is not defined

 

  雖然箭頭函數沒有arguments對象。但可以在包裝函數中把它提供給箭頭函數:

    function foo() {
        let bar = () => {
            console.log(arguments[0]);//5
        }
        bar()
    }
    foo(5);

 

  箭頭函數不能用作構造函數

  和new一起使用會拋出異常

var Foo = () => {};
var foo = new Foo(); // TypeError: Foo is not a constructor

 

  箭頭函數沒有prototype屬性

var Foo = () => {};
console.log(Foo.prototype); // undefined

 

  返回對象字面量

  記住用params => {object:literal}這種簡單的語法返回對象字面量是行不通的。

var func = () => { foo: 1 };
// Calling func() returns undefined!
var func = () => ({foo: 1});
//所以,記得用圓括號把對象字面量包起來:

var func = () => { foo: function() {} };
// SyntaxError: function statement requires a name

 

  箭頭函數也不能使用super和new.target

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM