箭头功能与功能
#javascript #关闭 #es6 #ecmascript

在JavaScript中,箭头函数提供了一种简洁的语法,用于从其OOP行李中剥离的匿名函数表达式。它们是功能能力子集中的句法糖。两者都可以用作捕获外部范围变量的封闭。
箭头功能是Ecmascript 2015标准的一部分,也称为ES6。我们将把箭头函数ES6语法的变化拆开为其类似函数的实现,并讨论差异。
本文熟悉传统功能,并通过在两种语言机制之间划分相似之处在先验知识上。

语法

“胖箭头”语法=>专用于箭头函数,因此名称。
箭头功能声明

(arg1, arg2, ..., argN) => expression

等效匿名函数:

(function (arg1, arg2, ..., argN) {
  return expression;
}).bind(this)

这里发生了很多事情:省略关键字,隐式return语句,this上下文绑定。下面分别讨论了每个方面。

语义
返回表达式

与普通函数不同(匿名或其他功能),箭头函数隐式返回评估的表达式而无需使用return语句。
箭头功能:

(arg1, arg2, ..., argN) => expression

等效匿名函数:

function (arg1, arg2, ..., argN) {
  return expression;
}

这里发生了很多事情:省略关键字,隐式return语句,this上下文绑定。下面分别讨论了每个方面。

语义
返回表达式

与普通函数不同(匿名或其他函数),箭头函数隐式返回评估的表达式而无需使用return语句。

箭头功能:

(arg1, arg2, ..., argN) => expression

等效匿名函数:

function (arg1, arg2, ..., argN) {
  return expression;
}

一旦您习惯了语法,您将欣赏代码变短的数量,并且永远不会返回。

块语句

简短的返回表达语法不能表示语句序列。那就是熟悉的块语句{}的来源。在卷曲括号内,您必须明确地将功能的return结果。
箭头功能:

(arg1, arg2, ..., argN) => {
  let result = doSomething();
  doDependentThing(result);
  return result;
}

等效匿名函数:

function (arg1, arg2, ..., argN) {
  let result = doSomething();
  doDependentThing(result);
  return result;
}

现在的功能看起来更相似,不是吗?

对象表达式

函数通常返回新构建的对象。有一个捕捉:对象声明符号{}与块语句语法没有区别。解决方案是用()包围内联物体以使其表达式。
箭头功能:

(arg1, arg2, ..., argN) => ({
  prop1: value1,
  prop2: value2,
  ...,
  propN: valueN
})

等效匿名函数:

function (arg1, arg2, ..., argN) {
  return {
    prop1: value1,
    prop2: value2,
    ...,
    propN: valueN
  };
}

单个参数

对于只有一个参数的箭头功能的特殊情况,有一个额外的句法糖。您可以省略围绕争论的括号。
箭头功能:

arg => expression

等效匿名函数:

function (arg) {
  return expression;
}

没有参数

带有参数的箭头函数只是空括号的边缘情况。与单个参数语法不同,这里需要括号。
箭头功能:

() => expression

等效匿名函数:

function () {
  return expression;
}

上下文绑定

让我们谈谈房间里的大象。除了箭头功能外,这个(双关语)一直是JavaScript中令人困惑的话题。
功能可以访问保存运行时分配的上下文的特殊变量this。问题在于该值取决于调用函数的方式而变化。

通常是错误的。

回调是主要用例,在大多数情况下,您需要访问在声明时间定义的this上下文,而不是调用。

您会发现自己在以下关闭样板上撒上代码:

let self = this;
let callback = function () {
  self.doSomething();
};

或重新绑定以避免回调中的self

let callback = function () {
  this.doSomething();
};
callback = callback.bind(this);

相比之下,箭头函数不提供自己的this上下文,而是继承当前的“词汇”范围。它们自然适合内联回调。

等效箭头功能:

let callback = () => void this.doSomething();

void操作员丢弃了this.doSomething()返回的结果,如果有的话。实际上,通过结果通常可以,并且可以省略void。块语句{}是忽略结果的另一种(也许更好)。

类方法

箭头函数由于this上下文的性质而在课堂上派上用场。从类方法外调用时,普通方法容易失去班级上下文。箭头方法不受此问题的影响。
箭头方法语法不过是一个类属性声明,并具有代替值的箭头函数。请注意,类属性是在Ecmascript 2017规范中引入的。

箭头方法(箭头功能属性):

class Example {
  constructor(arg) {
    this.arg = arg;
  }

  callback = () => {
    console.log(this.arg);
  }
}

等效的ES6类方法:

class Example {
  constructor(arg) {
    this.arg = arg;
    this.callback = this.callback.bind(this);
  }

  callback() {
    console.log(this.arg);
  }
}

示例
循环重构

单个参数在阵列方法回调中很常见,例如map()及其表兄弟,可以迭代项目。
循环在一系列项目上:

let ids = [];
for (let i = 0; i < items.length; i++) {
  ids.push(items[i].id);
}
return ids;

等效的传统函数实施:

let ids = items.map(function (item) {
  return item.id;
});

等效箭头函数实现:

let ids = items.map(item => item.id);

这个示例生动地证明了箭头功能提供的代码压缩水平,而无需牺牲可读性甚至改进。


在现代JavaScript代码中享受箭头功能的实用性!