javascript中的多個箭頭功能是什麼意思?

本文翻譯自:What do multiple arrow functions mean in javascript?

I have been reading a bunch of react code and I see stuff like this that I don't understand: 我一直在讀一堆react代碼,我看到一些我不明白的東西:

handleChange = field => e => {
  e.preventDefault();
  /// Do something here
}

#1樓

參考:https://stackoom.com/question/2DYKo/javascript中的多個箭頭功能是什麼意思


#2樓

Think of it like this, every time you see a arrow, you replace it with function . 這樣想吧,每次看到箭頭時,都將其替換爲function
function parameters are defined before the arrow. function parameters在箭頭之前定義。
So in your example: 因此,在您的示例中:

field => // function(field){}
e => { e.preventDefault(); } // function(e){e.preventDefault();}

and then together: 然後一起:

function (field) { 
    return function (e) { 
        e.preventDefault(); 
    };
}

From the docs : 從文檔

// Basic syntax:
(param1, param2, paramN) => { statements }
(param1, param2, paramN) => expression
   // equivalent to:  => { return expression; }

// Parentheses are optional when there's only one argument:
singleParam => { statements }
singleParam => expression

#3樓

Understanding the available syntaxes of arrow functions will give you an understanding of what behaviour they are introducing when 'chained' like in the examples you provided. 瞭解箭頭函數可用語法將使您瞭解“鏈接”時它們所引入的行爲,如您提供的示例中所示。

When an arrow function is written without block braces, with or without multiple parameters, the expression that constitutes the function's body is implicitly returned. 當編寫不帶大括號,帶有或不帶有多個參數的箭頭函數時,將隱式返回構成函數主體的表達式。 In your example, that expression is another arrow function. 在您的示例中,該表達式是另一個箭頭函數。

No arrow funcs              Implicitly return `e=>{…}`    Explicitly return `e=>{…}` 
---------------------------------------------------------------------------------
function (field) {         |  field => e => {            |  field => {
  return function (e) {    |                             |    return e => {
      e.preventDefault()   |    e.preventDefault()       |      e.preventDefault()
  }                        |                             |    }
}                          |  }                          |  }

Another advantage of writing anonymous functions using the arrow syntax is that they are bound lexically to the scope in which they are defined. 使用箭頭語法編寫匿名函數的另一個優點是將它們按詞法綁定到定義它們的範圍。 From 'Arrow functions' on MDN : MDN上的“箭頭功能”

An arrow function expression has a shorter syntax compared to function expressions and lexically binds the this value. 箭頭函數表達式的語法比函數表達式短,並且在詞法上綁定了值。 Arrow functions are always anonymous . 箭頭函數始終是匿名的

This is particularly pertinent in your example considering that it is taken from a application. 考慮到它是從應用程序中獲取的,這在您的示例中特別相關。 As as pointed out by @naomik, in React you often access a component's member functions using this . 正如@naomik指出的那樣,在React中,您經常使用this訪問組件的成員函數 For example: 例如:

Unbound                     Explicitly bound            Implicitly bound 
------------------------------------------------------------------------------
function (field) {         |  function (field) {       |  field => e => {
  return function (e) {    |    return function (e) {  |    
      this.setState(...)   |      this.setState(...)   |    this.setState(...)
  }                        |    }.bind(this)           |    
}                          |  }.bind(this)             |  }

#4樓

That is a curried function 那是一個咖喱函數

First, examine this function with two parameters … 首先,使用兩個參數檢查此功能……

const add = (x, y) => x + y
add(2, 3) //=> 5

Here it is again in curried form … 這裏又是咖喱形式的……

const add = x => y => x + y

Here is the same 1 code without arrow functions … 這是沒有箭頭功能的相同1個代碼……

const add = function (x) {
  return function (y) {
    return x + y
  }
}

Focus on return 專注於return

It might help to visualize it another way. 用另一種方式可視化可能會有所幫助。 We know that arrow functions work like this – let's pay particular attention to the return value . 我們知道箭頭函數是這樣工作的-讓我們特別注意返回值

const f = someParam => returnValue

So our add function returns a function – we can use parentheses for added clarity. 因此,我們的add函數返回一個函數 –我們可以使用括號來增加清晰度。 The bolded text is the return value of our function add 粗體字是我們函數add的返回值

const add = x => (y => x + y)

In other words add of some number returns a function 換句話說,一些數字的add返回一個函數

add(2) // returns (y => 2 + y)

Calling curried functions 調用咖喱函數

So in order to use our curried function, we have to call it a bit differently … 因此,爲了使用我們的curried函數,我們必須對其進行一些不同的調用……

add(2)(3)  // returns 5

This is because the first (outer) function call returns a second (inner) function. 這是因爲第一個(外部)函數調用返回了第二個(內部)函數。 Only after we call the second function do we actually get the result. 只有在調用第二個函數之後,我們才真正得到結果。 This is more evident if we separate the calls on two lines … 如果我們將呼叫分隔在兩行上,則更明顯……

const add2 = add(2) // returns function(y) { return 2 + y }
add2(3)             // returns 5

Applying our new understanding to your code 將我們的新知識應用於您的代碼

related: ”What's the difference between binding, partial application, and currying?” 相關: “綁定,部分應用和柯林有什麼區別?”

OK, now that we understand how that works, let's look at your code 好,現在我們瞭解了它的工作原理,讓我們看一下您的代碼

handleChange = field => e => {
  e.preventDefault()
  /// Do something here
}

We'll start by representing it without using arrow functions … 我們將從不使用箭頭功能來表示它開始……

handleChange = function(field) {
  return function(e) {
    e.preventDefault()
    // Do something here
    // return ...
  };
};

However, because arrow functions lexically bind this , it would actually look more like this … 但是,由於arrow函數用詞法綁定了this ,因此實際上看起來更像這樣……

handleChange = function(field) {
  return function(e) {
    e.preventDefault()
    // Do something here
    // return ...
  }.bind(this)
}.bind(this)

Maybe now we can see what this is doing more clearly. 也許現在我們可以更清楚地看到它在做什麼。 The handleChange function is creating a function for a specified field . handleChange函數正在爲指定field創建一個函數。 This is a handy React technique because you're required to setup your own listeners on each input in order to update your applications state. 這是一種方便的React技術,因爲您需要在每個輸入上設置自己的偵聽器以更新您的應用程序狀態。 By using the handleChange function, we can eliminate all the duplicated code that would result in setting up change listeners for each field. 通過使用handleChange函數,我們可以消除所有重複的代碼,這些代碼將導致爲每個字段設置change偵聽器。 Cool! 涼!

1 Here I did not have to lexically bind this because the original add function does not use any context, so it is not important to preserve it in this case. 1在這裏,我不必用詞法綁定this因爲原始的add函數不使用任何上下文,因此在這種情況下保留它並不重要。


Even more arrows 甚至更多的箭

More than two arrow functions can be sequenced, if necessary - 如有必要,可以排序兩個以上的箭頭功能-

const three = a => b => c =>
  a + b + c

const four = a => b => c => d =>
  a + b + c + d

three (1) (2) (3) // 6

four (1) (2) (3) (4) // 10

Curried functions are capable of surprising things. 咖喱函數能夠使人驚訝。 Below we see $ defined as a curried function with two parameters, yet at the call site, it appears as though we can supply any number of arguments. 在下面,我們看到$被定義爲具有兩個參數的咖喱函數,但是在調用站點,似乎我們可以提供任意數量的參數。 Currying is the abstraction of arity - 柯里是抽象元數 -

 const $ = x => k => $ (k (x)) const add = x => y => x + y const mult = x => y => x * y $ (1) // 1 (add (2)) // + 2 = 3 (mult (6)) // * 6 = 18 (console.log) // 18 $ (7) // 7 (add (1)) // + 1 = 8 (mult (8)) // * 8 = 64 (mult (2)) // * 2 = 128 (mult (2)) // * 2 = 256 (console.log) // 256 

Partial application 部分申請

Partial application is a related concept. 部分應用是一個相關的概念。 It allows us to partially apply functions, similar to currying, except the function does not have to be defined in curried form - 它允許我們部分地應用函數,類似於currying,除了不必以咖喱形式定義函數-

const partial = (f, ...a) => (...b) =>
  f (...a, ...b)

const add3 = (x, y, z) =>
  x + y + z

partial (add3) (1, 2, 3)   // 6

partial (add3, 1) (2, 3)   // 6

partial (add3, 1, 2) (3)   // 6

partial (add3, 1, 2, 3) () // 6

partial (add3, 1, 1, 1, 1) (1, 1, 1, 1, 1) // 3

Here's a working demo of partial you can play with in your own browser - 這是您可以在自己的瀏覽器中播放的partial工作演示-

 const partial = (f, ...a) => (...b) => f (...a, ...b) const preventDefault = (f, event) => ( event .preventDefault () , f (event) ) const logKeypress = event => console .log (event.which) document .querySelector ('input[name=foo]') .addEventListener ('keydown', partial (preventDefault, logKeypress)) 
 <input name="foo" placeholder="type here to see ascii codes" size="50"> 


#5樓

A general tip , if you get confused by any of new JS syntax and how it will compile , you can check babel . 一般提示,如果您對任何新的JS語法及其編譯方式感到困惑,則可以檢查babel For example copying your code in babel and selecting the es2015 preset will give an output like this 例如,將您的代碼複製到babel中並選擇es2015預設將給出這樣的輸出

handleChange = function handleChange(field) {
 return function (e) {
 e.preventDefault();
  // Do something here
   };
 };

巴別塔


#6樓

The example in your question is that of a curried function which makes use of arrow function and has an implicit return for the first argument. 您問題中的示例是使用arrow functioncurried function示例,並且第一個參數具有implicit return

Arrow function lexically bind this ie they do not have their own this argument but take the this value from the enclosing scope 箭頭函數用詞法綁定此對象,即它們沒有自己的this參數,但從封閉範圍獲取this

An equivalent of the above code would be 與上面的代碼等效

const handleChange = (field) {
  return function(e) {
     e.preventDefault();
     /// Do something here
  }.bind(this);
}.bind(this);

One more thing to note about your example is that define handleChange as a const or a function. 關於您的示例要注意的另一件事是將handleChange定義爲const或函數。 Probably you are using it as part of a class method and it uses a class fields syntax 可能您將其用作類方法的一部分,並且使用了class fields syntax

so instead of binding the outer function directly, you would bind it in the class constructor 因此,與其直接綁定外部函數,不如將其綁定到類構造函數中

class Something{
    constructor(props) {
       super(props);
       this.handleChange = this.handleChange.bind(this);
    }
    handleChange(field) {
        return function(e) {
           e.preventDefault();
           // do something
        }
    }
}

Another thing to note in the example is the difference between implicit and explicit return. 該示例中要注意的另一件事是隱式和顯式返回之間的區別。

const abc = (field) => field * 2;

Above is an example of implicit return ie. 上面是隱式返回的示例,即。 it takes the value field as argument and returns the result field*2 which explicitly specifying the function to return 它以值字段作爲參數並返回結果field*2 ,該field*2顯式指定要返回的函數

For an explicit return you would explicitly tell the method to return the value 對於顯式返回,您將顯式告訴方法返回值

const abc = () => { return field*2; }

Another thing to note about arrow functions is that they do not have their own arguments but inherit that from the parents scope as well. 關於箭頭函數要注意的另一件事是它們沒有自己的arguments但也從父級範圍繼承了該arguments

For example if you just define an arrow function like 例如,如果您僅定義一個箭頭函數,例如

const handleChange = () => {
   console.log(arguments) // would give an error on running since arguments in undefined
}

As an alternative arrow functions provide the rest parameters that you can use 作爲替代,箭頭函數提供您可以使用的其餘參數

const handleChange = (...args) => {
   console.log(args);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章