javascript - “箭头功能”和“功能”是否等效/可互换?

标签 javascript ecmascript-6 arrow-functions

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; dr:不!箭头函数和函数声明/表达式不等效,不能盲目替换。
如果要替换的函数不使用thisarguments并且未使用new调用,则可以。



如此频繁:这取决于。箭头函数与函数声明/表达式的行为不同,因此让我们首先看一下它们的区别:

1.词法thisarguments

箭头函数没有自己的thisarguments绑定。相反,这些标识符像任何其他变量一样在词法范围内解析。这意味着在箭头函数内部,thisarguments引用定义了箭头函数的环境中的thisarguments的值(即,箭头函数“外”):



// Example using a function expression
function createObject() {
  console.log('Inside `createObject`:', this.foo);
  return {
    foo: 42,
    bar: function() {
      console.log('Inside `bar`:', this.foo);
    },
  };
}

createObject.call({foo: 21}).bar(); // override `this` inside createObject







// Example using a arrow function
function createObject() {
  console.log('Inside `createObject`:', this.foo);
  return {
    foo: 42,
    bar: () => console.log('Inside `bar`:', this.foo),
  };
}

createObject.call({foo: 21}).bar(); // override `this` inside createObject





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

如果需要访问当前环境的this,这将使箭头功能有用:

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

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


请注意,这也意味着无法用this.bind设置箭头功能的.call

如果您对this不太熟悉,请考虑阅读


MDN - this
YDKJS - this & Object prototypes


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

ES2015区分了可调用函数和可构造函数。如果一个函数是可构造的,则可以使用newnew User()对其进行调用。如果一个函数是可调用的,则可以在不使用new的情况下对其进行调用(即正常的函数调用)。

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

如果试图调用不可调用函数或构造不可构造函数,则会出现运行时错误。



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

可更换的:


不使用thisarguments的函数。
.bind(this)一起使用的功能


不可更换:


构造函数
添加到原型的函数/方法(因为它们通常使用this
可变参数函数(如果它们使用arguments(请参见下文))




让我们使用您的示例仔细看一下:

构造函数

这是行不通的,因为箭头函数不能用new调用。继续使用函数声明/表达式或使用class

原型方法

很有可能不是,因为原型方法通常使用this访问实例。如果他们不使用this,则可以将其替换。但是,如果您主要关心简洁的语法,请使用class及其简洁的方法语法:

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(或arguments),则不能使用箭头功能!

可变函数

由于箭头函数没有自己的arguments,因此不能简单地用箭头函数替换它们。但是,ES2015引入了使用arguments的替代方法:rest parameter

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

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




相关问题:


When should I use Arrow functions in ECMAScript 6?
Do ES6 arrow functions have their own arguments or not?
What are the differences (if any) between ES6 arrow functions and functions bound with Function.prototype.bind?
How to use arrow functions (public class fields) as class methods?


更多资源:


MDN - Arrow functions
YDKJS - Arrow functions

关于javascript - “箭头功能”和“功能”是否等效/可互换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45527065/

相关文章:

javascript - 如何使用 ecmascript 或 SPServices 获取类型为个人或组的 SharePoint 列表字段值?

javascript - Ecma6 promise : how to use Ecma6 promise to rewrite jquery $. 什么时候?

javascript - 箭头函数中的 "this"与该箭头函数之外的 "that"中的 "var that = this"是否相同?

javascript - 从 ReactJS 中导入的函数更改类状态

javascript - 调整大小停止后无法再次调整垂直标尺的大小

javascript - CDN 支持捆绑

javascript - AngularJS/JavaScript 从 Localstorage 数组中删除特定元素

javascript - 计算字符串的实际长度,就像我们使用插入符一样

javascript - 如何根据数组数组中的前一个元素过滤元素

javascript - jQuery map 中的箭头函数