ES2015中的箭头函数提供了更简洁的语法。

我现在可以用箭头函数替换我所有的函数声明/表达式吗? 我要注意什么?

例子:

构造函数

function User(name) {
  this.name = name;
}

// vs

const User = name => {
  this.name = name;
};

原型方法

User.prototype.getName = function() {
  return this.name;
};

// vs

User.prototype.getName = () => this.name;

对象(文字)方法

const obj = {
  getName: function() {
    // ...
  }
};

// vs

const obj = {
  getName: () => {
    // ...
  }
};

回调

setTimeout(function() {
  // ...
}, 500);

// vs

setTimeout(() => {
  // ...
}, 500);

可变的函数

function sum() {
  let args = [].slice.call(arguments);
  // ...
}

// vs
const sum = (...args) => {
  // ...
};

tl;博士:不!箭头函数和函数声明/表达式是不等价的,不能盲目替换。 如果要替换的函数没有使用this,参数,并且没有使用new调用,则是。


通常情况下:这要看情况。箭头函数与函数声明/表达式有不同的行为,所以让我们先看看区别:

1. 词汇本和论点

箭头函数没有自己的this或参数绑定。相反,这些标识符像其他变量一样在词法作用域中解析。这意味着在一个箭头函数中,this和arguments指向定义箭头函数的环境中的this和arguments的值。“outside”箭头函数):

//函数表达式的示例 函数createObject() console.log('Inside ' createObject ':', this.foo); 返回{ foo: 42岁 Bar: function() { console.log('Inside ' bar ':', this.foo); }, }; } createObject。调用({foo: 21}) . bar ();//重写createObject中的this

//使用箭头函数的例子 函数createObject() console.log('Inside ' createObject ':', this.foo); 返回{ foo: 42岁 酒吧:()= > console.log(“内部”酒吧‘:’,this.foo), }; } createObject。调用({foo: 21}) . bar ();//重写createObject中的this

在函数表达式的情况下,this指的是在createObject中创建的对象。在箭头函数的情况下,this指的是createObject本身的this。

这使得箭头函数非常有用,如果你需要访问当前环境的This:

// currently common pattern
var that = this;
getData(function(data) {
  that.data = data;
});

// better alternative with arrow functions
getData(data => {
  this.data = data;
});

注意,这也意味着不可能用.bind或.call来设置箭头函数的this。

如果你对此不是很熟悉,可以考虑阅读

MDN -这个 YDKJS -这个&对象原型

2. 不能用new调用箭头函数

ES2015区分了可调用函数和可构造函数。如果一个函数是可构造的,它可以用new调用,即new User()。如果一个函数是可调用的,它可以被调用而不需要new(即普通的函数调用)。

通过函数声明/表达式创建的函数既可构造又可调用。 箭头函数(和方法)只能被调用。 类构造函数只能是可构造的。

如果您试图调用一个不可调用的函数或构造一个不可构造的函数,您将得到一个运行时错误。


知道了这一点,我们可以陈述如下。

可更换:

不使用this或参数的函数。 使用.bind(this)的函数

没有可替换的:

构造器函数 添加到原型的函数/方法(因为它们通常使用这个) 可变函数(如果它们使用参数(见下文)) 生成器函数,需要函数*符号


让我们用你的例子来仔细看看:

构造函数

这将不起作用,因为箭头函数不能用new调用。保持使用函数声明/表达式或使用类。

原型方法

很可能不是,因为原型方法通常使用它来访问实例。如果他们不用这个,你可以换一个。然而,如果你主要关心简洁的语法,使用类和它的简洁的方法语法:

class User {
  constructor(name) {
    this.name = name;
  }
  
  getName() {
    return this.name;
  }
}

对象方法

对象文字中的方法也是如此。如果方法想通过this引用对象本身,请继续使用函数表达式,或者使用新的方法语法:

const obj = {
  getName() {
    // ...
  },
};

回调

视情况而定。如果你要对外层this进行混叠或者使用.bind(this),你一定要替换它:

// old
setTimeout(function() {
  // ...
}.bind(this), 500);

// new
setTimeout(() => {
  // ...
}, 500);

但是:如果调用回调的代码显式地将this设置为特定的值,就像事件处理程序(尤其是jQuery)经常发生的情况一样,并且回调使用this(或参数),那么您就不能使用箭头函数!

可变的函数

由于箭头函数没有自己的参数,所以不能简单地用箭头函数替换它们。然而,ES2015引入了一种使用参数的替代方法:rest形参。

// old
function sum() {
  let args = [].slice.call(arguments);
  // ...
}

// new
const sum = (...args) => {
  // ...
};

相关问题:

什么时候我应该在ECMAScript 6中使用箭头函数? ES6箭头函数是否有自己的参数? ES6箭头函数和Function.prototype.bind绑定的函数之间有什么区别(如果有的话)? 如何使用箭头函数(公共类字段)作为类方法?

更多资源:

MDN -箭头函数 箭头函数


箭头函数=>迄今为止最好的ES6特性。他们是非常了不起的 ES6的强大补充,我经常使用。

等等,你不能在你的代码中到处使用箭头函数,它不会在所有情况下工作,比如箭头函数不可用。毫无疑问,箭头函数是一个很好的补充,它使代码变得简单。

但是当需要动态上下文时不能使用箭头函数:定义方法、使用构造函数创建对象、在处理事件时从中获取目标。

不应该使用箭头函数,因为:

他们没有这个 它使用“词法作用域”来确定“this”的值 应该是。在简单的词汇范围中,它使用了“this” 在函数体内部。 他们没有争论 箭头函数没有参数对象。但都一样 可以使用rest参数实现功能。

let sum = (...args) => args.reduce((x, y) => x + y, 0);
sum(3, 3, 1) // output: 7

它们不能与新的一起使用 箭头函数不能是构造函数,因为它们没有原型属性。

何时使用箭头函数,何时不使用:

不要在object literal中使用add函数作为属性,因为我们 不能访问这个。 函数表达式最适合用于对象方法。箭头功能 最适合用于回调或map、reduce或forEach等方法。 对按名称调用的函数使用函数声明(因为 他们升起)。 回调时使用箭头函数(因为它们更简洁)。


在function.prototype中使用箭头函数。调用,我在对象原型上做了一个helper函数:

  // Using
  // @func = function() {use this here} or This => {use This here}
  using(func) {
    return func.call(this, this);
  }

使用

  var obj = {f:3, a:2}
  .using(This => This.f + This.a) // 5

Edit

你不需要帮手。你可以这样做:

var obj = {f:3, a:2}
(This => This.f + This.a).call(undefined, obj); // 5

它们并不总是相等的。在这种情况下,你不能简单地使用箭头函数而不是常规函数。

箭头函数不能用作构造函数

TLDR:

这是因为Arrow Functions使用This关键字的方式。如果JS看到一个箭头函数作为“构造函数”被调用,它会简单地抛出一个错误。使用常规函数来修复错误。

更详细的解释:

这是因为对象的“构造函数”依赖于This关键字才能被修改。

通常,this关键字总是引用全局对象。(在浏览器中它是窗口对象)。

但是,当你这样做的时候:

function personCreator(name) {
   this.name = name;
}

const person1 = new personCreator('John');

new关键字发挥了一些魔力,使personCreator中的this关键字最初是一个空对象,而不是引用全局对象。在此之后,一个名为name的新属性将在该空对象中创建,其值将为'John'。最后,返回this对象。

如我们所见,new关键字将this的值从引用全局对象更改为空对象{}。

箭头函数不允许修改它们的this对象。它们的this对象总是来自静态创建它们的作用域的对象。这被称为静态词法作用域。这就是为什么您不能使用箭头函数执行绑定、应用或调用等操作。简单地说,它们的this被锁定为创建它们时作用域的this的值。这是有意为之。

正因为如此:D,箭头函数不能用作“构造函数”。

注:

词法作用域就是创建函数的区域。例如:

function personCreator(name) {
    this.name = name;

    const foo = () => {
        const bar = () => {
            console.log(this); // Output: { name: 'John' }
        }

        console.log(this); // Output: { name: 'John' }
    
        bar();
    }

    foo();
}

const person1 = new personCreator('John');

bar的词法范围是foo中的所有内容。bar的this值就是foo的值,也就是personCreator的值。