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);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值