wangyahui6

JavaScript: 箭头函数(初学者) – Hacker Noon

wangyahui6 · 2017-06-11翻译 · 271阅读 原文链接

上周我发布了一篇适合初学者阅读,关于this关键字的 文章. 箭头函数这个话题因为太大未被包含在那篇文章中,所以在这篇文章中对箭头函数进行补充. 阅读这篇文章,了解箭头函数的基本知识!


优点 #1: 更简洁的语法

我们看一下常规的函数:

function funcName(params) {
   return params + 2;
 }
funcName(2);
// 4

以上的代码表明了我们使用箭头函数的其中一个原因就是更简洁的语法,上述代码用箭头函数表示只需要一行就够了。

var funcName = (params) => params + 2
funcName(2);
// 4

相当酷吧. 这个例子虽然很简单,但希望它阐明了我的观点. 下面让我们来看一下更深入一点的箭头函数语法:

**(**parameters**) => {** statements **}**

如果我们没有参数,我们可以像下面这样表达箭头函数:

**() => {** statements **}**

当只有一个参数时,圆括号是可以省略的:

parameters **=> {** statements **}**

最后,如果你只是返回一个表达式,你可以省略大括号:

parameters **=>** expression
// is equivalent to:
function (parameters){
  return expression;
}

好了,现在你已经知道语法了,来一个例子怎么样? 打开你chrome的开发者工具的控制台(Windows: Ctrl + Shift + J)(Mac: Cmd + Option + J),然后输入:

var double = num => num * 2

如你所见,我们将一个箭头函数赋值给double变量. 这个箭头函数有一个参数, num . 因为只有一个参数,所以我们省略了参数两边的圆括号. 因为我们想要返回 num * 2的值, 所以我们也省略了要返回的表达式两边的大括号. 让我们来调用一下这个函数看看效果:

double(2);
// 4
double(3);
// 6

优点 #2: 不绑定this

在我们继续之前,你应该对关键字this很熟悉,知道它的工作原理. 如果你想学习或者需要复习一下, 请阅读 我的博客.

和普通函数不同的是箭头函数不绑定this. 替代地,this就是在字面上被绑定 (例如,this 保持了它原本在上下文的含义).

一个例子能更清楚一点. 在你的console中,创建一个构造函数,然后创建一个它的实例:

function Counter() {
  this.num = 0;
}
var a = new Counter();

从我的上篇文章中你应该知道,构造函数的this值被绑定到了新创建的对象上, 在这个例子中, 就是a对象. 这也是为什么我们打印a.num 得到 0的原因

console.log(a.num);
// 0

如果我们想每秒钟都增加a.num的值那? 我们可以用 setInterval() 函数. setInterval() 是一个会在设定的毫秒数之后重复调用另一个函数的函数. 让我们把它加入到 Counter 函数中:

function Counter() {
  this.num = 0;
  this.timer = setInterval(function add() {
    this.num++;
    console.log(this.num);
  }, 1000);
}

代码除了增加了一个变量this.timer, 然后把我们的 setInterval 函数赋值给它,其他的保持不变. 每1000毫秒 (1s) 代码将会运行一次. this.num 将会加1, 然后会被打印到控制台. 让我们来运行一下试一试. 我们再一次在控制台创建一个Counter的实例:

var b = new Counter();
// NaN
// NaN
// NaN
// ...

如你所见,这函数每秒都在控制台打印. 但是结果不是我们期望的. NaN (Not a Number) 被打印. 是哪里错了? 首先, 运行下面的代码终止烦人的打印:

clearInterval(b.timer);

让我们回去看一下. 我们的 setInterval 函数没有在一个声明的函数上调用. 它也没有使用new关键字调用 (只有Counter() 函数是). 最后, 我们没有使用 call, bind, 或者 apply. setInterval 就是一个普通的函数. 实际上, 在setInterval函数中的this被绑定到全局对象上去了! 让我们打印this的值来验证一下:

function Counter() {
  this.num = 0;
this.timer = setInterval(function add() {
    console.log(this);
  }, 1000);
}
var b = new Counter();

如你所见, window被每秒打印出来了. 清除一下打印:

clearInterval(b.timer);

回到我们最初的函数. 它之所以打印 NaN是因为this.num是引用的window对象上的num属性 ( window.num是不存在的),而不是我们刚刚创建的b对象 ( b.num ).

我们应该如何修复那? 使用箭头函数! 我们需要一个不绑定this的函数. 使用箭头函数, this绑定这个上下文中的值. 让我们在Counter中使用箭头函数.

function Counter() {
  this.num = 0;
  this.timer = setInterval(() => {
    this.num++;
    console.log(this.num);
  }, 1000);
}
var b = new Counter();
// 1
// 2
// 3
// ...

如你所见,控制台开始打印增长的数字 — 它起作用了! 被 Counter 构造函数创建的this绑定被保存下来了.在setInterval函数中,this指向我们新创建的b对象!

你可以清除打印:

clearInterval(b.timer);

为了证明这个机制,我们可以再次打印setInterval函数内部的this. 我们在Counter函数中创建一个变量that. 我们将会打印true如果setInterval函数内部的this值等于Counter函数中的this(通过 that )值:

function Counter() {
  var that = this;
this.timer = setInterval(() => {
    console.log(this === that);
  }, 1000);
}
var b = new Counter();
// true
// true
// ...

正如期望的,每隔一秒打印一个true!再一次,清空打印:

clearInterval(b.timer);

结论

希望这篇文章有帮助你了解箭头函数的这两个优点:

  1. 更简洁的语法

  2. 不绑定this

说明一下,箭头函数的内容远大于这篇文章所讲的. 但是这篇文章可以给你很好基础去学习更深层的只是! 如果你有关于这个主题的资源,请留言.


❤ 如果你觉得这篇文章有帮助,请点赞! 不要忘记看看我的其他文章

译者wangyahui6尚未开通打赏功能

相关文章