在JavaScript中,多个箭头函数意味着什么?

在JavaScript中,多个箭头函数意味着什么?,javascript,ecmascript-6,arrow-functions,reactjs,Javascript,Ecmascript 6,Arrow Functions,Reactjs,我一直在读一堆代码,我看到这样的东西,我不明白: handleChange = field => e => { e.preventDefault(); /// Do something here } 这样想,每次看到箭头时,都会用函数替换它函数参数在箭头之前定义。 因此,在您的示例中: field => // function(field){} e => { e.preventDefault(); } // function(e){e.preventDefaul

我一直在读一堆代码,我看到这样的东西,我不明白:

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

这样想,每次看到箭头时,都会用
函数
替换它
函数参数
在箭头之前定义。
因此,在您的示例中:

field => // function(field){}
e => { e.preventDefault(); } // function(e){e.preventDefault();}
然后一起:

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

理解将使您了解当像您提供的示例中那样“链接”时,他们将引入什么行为

当编写不带大括号的arrow函数时,无论是否有多个参数,都会隐式返回构成函数体的表达式。在您的示例中,该表达式是另一个箭头函数

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()
  }                        |                             |    }
}                          |  }                          |  }
使用箭头语法编写匿名函数的另一个优点是,它们在词汇上与定义它们的范围相绑定。发件人:

箭头函数表达式的语法较短,并在词汇上绑定该值。箭头函数始终为空

考虑到它是从应用程序中获取的,这在您的示例中尤其重要。正如@naomik所指出的,在React中,您经常使用
this
访问a。例如:

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)             |  }
那是一个

首先,用两个参数检查此函数

const add = (x, y) => x + y
add(2, 3) //=> 5
这里又是咖喱的形式

const add = x => y => x + y
这是没有箭头函数的same1代码

const add = function (x) {
  return function (y) {
    return x + y
  }
}
handleChange = function(field) {
  return function(e) {
    e.preventDefault()
    // Do something here
    // return ...
  };
};

关注
返回

用另一种方式将其形象化可能会有所帮助。我们知道箭头函数是这样工作的–让我们特别注意返回值

const f = someParam => returnValue
换句话说,某个数字的
add
返回一个函数

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

调用curried函数

所以为了使用curried函数,我们必须用不同的方式调用它

add(2)(3)  // returns 5
这是因为第一个(外部)函数调用返回第二个(内部)函数。只有在调用第二个函数之后,我们才能真正得到结果。如果我们把两行电话分开,这一点就更明显了

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

将我们的新理解应用到您的代码中

相关的:

好了,现在我们了解了它的工作原理,让我们看看您的代码

handleChange = field => e => {
  e.preventDefault()
  /// Do something here
}
我们将首先表示它,而不使用箭头函数

const add = function (x) {
  return function (y) {
    return x + y
  }
}
handleChange = function(field) {
  return function(e) {
    e.preventDefault()
    // Do something here
    // return ...
  };
};
然而,由于arrow函数在词汇上绑定了这个
,所以它实际上看起来更像这样

handleChange = function(field) {
  return function(e) {
    e.preventDefault()
    // Do something here
    // return ...
  }.bind(this)
}.bind(this)
也许现在我们可以更清楚地看到它在做什么。
handleChange
函数正在为指定的
字段创建函数。这是一种方便的React技术,因为您需要在每个输入上设置自己的侦听器,以便更新应用程序状态。通过使用
handleChange
函数,我们可以消除所有会导致为每个字段设置
change
侦听器的重复代码。酷

1在这里,我不必对
this
进行词汇绑定,因为原始的
add
函数不使用任何上下文,因此在这种情况下保留它并不重要


更多箭头

如有必要,可以对两个以上的箭头功能进行排序-

constthree=a=>b=>c=>
a+b+c
常数四=a=>b=>c=>d=>
a+b+c+d
三(1)(2)(3)//6
四(1)(2)(3)(4)//10
Curried函数能够产生令人惊讶的结果。下面我们看到
$
被定义为一个带有两个参数的curried函数,但是在调用站点,似乎我们可以提供任意数量的参数。咖喱是对食物的抽象-

const$=x=>k=>
$(k(x))
常量添加=x=>y=>
x+y
常数mult=x=>y=>
x*y
$ (1)           // 1
(加上(2))/+2=3
(多(6))//*6=18
(console.log)//18
$ (7)            // 7
(加(1))/+1=8
(多(8))//*8=64
(多(2))//*2=128
(多(2))//*2=256

(console.log)//256
一般提示:如果您对任何新的JavaScript语法及其编译方式感到困惑,可以检查。例如,在Babel中复制代码并选择ES 2015预设将给出如下输出

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

您问题中的示例是一个
curried函数
,它使用
箭头函数
,第一个参数有一个
隐式返回

Arrow函数以词汇形式绑定此参数,即它们没有自己的
this
参数,而是从封闭范围中获取
this

上述代码的等效代码为

const handleChange = (field) {
  return function(e) {
     e.preventDefault();
     /// Do something here
  }.bind(this);
}.bind(this);
关于您的示例,需要注意的另一点是将
handleChange
定义为常量或函数。您可能将其作为类方法的一部分使用,并且它使用
类字段语法

因此,您可以在类构造函数中绑定外部函数,而不是直接绑定外部函数

class Something{
    constructor(props) {
       super(props);
       this.handleChange = this.handleChange.bind(this);
    }
    handleChange(field) {
        return function(e) {
           e.preventDefault();
           // do something
        }
    }
}
本例中需要注意的另一件事是隐式和显式返回之间的差异

const abc = (field) => field * 2;
上面是隐式返回ie的一个示例。它将值字段作为参数,并返回结果
字段*2
,该字段显式指定要返回的函数

对于显式返回,您将显式地告诉方法返回值

const abc = () => { return field*2; }
关于arrow函数,另一件需要注意的事情是,它们没有自己的
参数
,而是从父作用域继承这些参数

例如,如果您只定义一个箭头函数,如

const handleChange = () => {
   console.log(arguments) // would give an error on running since arguments in undefined
}
作为替代,箭头函数提供您可以使用的rest参数

const handleChange = (...args) => {
   console.log(args);
}

简短这可能不是完全相关的,但由于react用例中提到的问题(我一直碰到这个问题):这里没有明确提到双箭头函数的一个重要方面。 只有“第一个”箭头(函数)被命名(因此是“第一个”)
handleChange = task => event => { ... operations which uses both task and event... };