“箭头函数”和“函数”是否等效/可互换?

2024-05-01

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: No!箭头函数和函数声明/表达式并不等价,不能盲目替换。
如果您要替换的功能是not use this, arguments并且不被调用new, 好的。


正如经常发生的那样:这取决于。箭头函数与函数声明/表达式有不同的行为,所以让我们先看看差异:

1. 词汇this and arguments

箭头函数没有自己的函数this or arguments捆绑。相反,这些标识符像任何其他变量一样在词法范围内解析。这意味着在箭头函数内部,this and arguments参考值this and arguments在环境中箭头函数是defined在(即箭头函数“外部”):

// 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。在箭头函数的情况下,this指的是this of createObject itself.

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

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

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

Note这也意味着not可以设置箭头函数this with .bind or .call.

如果你不是很熟悉this,考虑阅读

  • MDN-这个 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

2. 不能用以下方式调用箭头函数new

ES2015 区分的函数是call能够和功能是构造有能力的。如果函数是可构造的,则可以使用以下命令调用它new, i.e. new User()。如果一个函数是可调用的,则无需调用它new(即正常的函数调用)。

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

如果您尝试调用不可调用的函数或构造不可构造的函数,您将收到运行时错误。


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

可更换:

  • 不使用的功能this or arguments.
  • 与使用的函数.bind(this)

Not可更换:

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

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

构造函数

这是行不通的,因为箭头函数不能用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);

But:如果调用回调的代码显式设置this到一个特定的值,事件处理程序经常出现这种情况,尤其是 jQuery,并且回调使用this (or arguments), you cannot使用箭头函数!

可变参数函数

由于箭头函数没有自己的arguments,你不能简单地用箭头函数替换它们。然而,ES2015 引入了一种替代方法arguments: the 剩余参数 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters.

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

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

相关问题:

  • 我什么时候应该在 ECMAScript 6 中使用箭头函数? https://stackoverflow.com/q/22939130/218196
  • ES6 箭头函数是否有自己的参数? https://stackoverflow.com/q/33288998/1048572
  • ES6 箭头函数和使用 Function.prototype.bind 绑定的函数之间有什么区别(如果有)? https://stackoverflow.com/q/32535110/1048572
  • 如何使用箭头函数(公共类字段)作为类方法? https://stackoverflow.com/q/31362292/1048572

更多资源:

  • MDN - 箭头函数 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

“箭头函数”和“函数”是否等效/可互换? 的相关文章

  • 如何使用 HTML 5 实现类似 gmail 的文件上传/附件

    我记得一些支持 Ajax 之类的选项 无回发世界 文件上传 隐藏的 iframe 使用 flash 对象 尽管我仍然好奇为什么使用 SWF 以及它提供什么优势 然而 通过查看博客 HTML 5 似乎很有前途 我尝试了一些小示例 它确实有效
  • 如何实时改变setInterval的速度

    我想知道如何实时更改 setInterval 的速度 例如 if score lt 10 repeater setInterval function spawnEnemy 1000 if score gt 10 repeater setIn
  • Angular 4 过滤器搜索自定义管道

    所以我试图构建一个自定义管道来在 ngFor 循环中执行多个值的搜索过滤器 我花了几个小时寻找一个好的工作示例 其中大多数都是基于以前的版本 并且似乎不起作用 所以我正在构建管道并使用控制台为我提供值 但是 我似乎无法显示输入文本 以下是我
  • Angular UI select:从远程服务获取数据

    我正在使用角度用户界面选择 https github com angular ui ui select https github com angular ui ui select 我查看了演示的可用位置这个笨蛋 http plnkr co
  • 如何判断一个网页是否支持jquery?

    确定网页是否启用 jquery 的最佳方法是什么 如果这是确定它的最佳方法 则使用 jquery 本身 if jQuery jquery object exists jQuery 并不神奇 它本质上只是一个大对象 您可以像检查任何其他对象一
  • 使用 jQuery Select2 清除下拉菜单

    我正在尝试使用奇妙的方式以编程方式清除下拉菜单Select2 http ivaynberg github com select2 图书馆 使用 Select2 远程 ajax 调用动态填充下拉列表query option HTML
  • 如何使 d3 饼图响应式?

    我有一个 PIE 图表 它工作正常 但我无法使其具有响应能力和可调整大小 我需要它与移动浏览器和 iPad 等兼容 div div
  • jQuery输入文件点击方法和IE上拒绝访问

    我尝试仅使用一个按钮作为输入文件 它在 Firefox Chrome Safari 中工作正常 但在 IE 中不行 提交表单时我总是收到 访问被拒绝 的消息 代码 input file click 有真正的解决方法吗 我在谷歌上浪费了大约2
  • 将 Firebase FCM 添加到 ReactJS 应用程序

    我正在尝试向我的 ReactJS 应用程序中的用户发送推送通知 我已添加 firebase 请求用户通知权限 这正在发挥作用 但现在我想注册设备令牌 但这给了我错误 消息传递 我们无法注册默认的 Service Worker 无法注册 Se
  • ES6继承:使用`super`访问父类的属性

    JavaScript 的super关键字 当我在 Chrome Babel TypeScript 上运行代码时 得到了不同的结果 我的问题是哪个结果是正确的 规范的哪一部分定义了这种行为 下面的代码 class Point getX con
  • 类中可以有生成器 getter 吗?

    我的意思是吸气剂是发电机 我相信这一切都是 ES6 也许像这样 class a get count let i 10 while i yield i let b new a for const i of b count console lo
  • 如何在画布上所有其他内容后面绘制图像? [复制]

    这个问题在这里已经有答案了 我有一块画布 我想用drawImage在画布上当前内容后面绘制图像 由于画布上已经有内容 我正在使用字面上的画布来创建包含图像的画布 因此我无法真正先绘制图像 所以我无法使用drawImage在我呈现其余内容之前
  • 如何重复 ajax 请求,直到满足 RxJS Observable 的条件?

    我正在尝试重复请求 直到响应包含使用 RxJS 的数据 此时我想调用成功 或失败 处理程序 但我在使用 RxJS 时遇到了麻烦 这是我目前的方法 redux observable action observable mergeMap gt
  • 尝试使用 Javascript 解决对称差异

    我正在尝试找出对称的解决方案 使用 javascript 完成以下任务的差异 目标 接受未指定数量的数组作为参数 保留数组中数字的原始顺序 不删除单个数组中数字的重复项 删除数组中出现的重复项 因此 例如 如果输入是 1 1 2 6 2 3
  • 使用 ref 触发反应 dropzone 不起作用

    我正在实现这个库 https github com felixrieseberg React Dropzone Component https github com felixrieseberg React Dropzone Compone
  • PDF 在 Safari 中隐藏 Jquery Modal

    这是与我有关的事情this https stackoverflow com questions 24052681 pdf hide jquery modal in ie问题 在 IE 中 我在对话框中使用 iframe 解决了问题 所以它工
  • ThreeJS 中阴影的奇怪行为

    所以我有一个 ThreeJS 场景 并且添加了一些球体 多材质 我还添加了定向光 this light new THREE DirectionalLight 0xFFFFFF 1 this light position set 2 10 2
  • Jwt 签名和前端登录身份验证

    我有这个特殊的 jwt sign 函数 Backend const token jwt sign id user id process env TOKEN SECRET expiresIn 1m res header auth token
  • MongoDB:javascript执行失败:无法在 src/mongo/shell/collection.js 保存 DBQuery 对象

    在 MongoDb 中 当我尝试修改集合中的现有文档时 它会生成以下异常 javascript execution failed can t save a DBQuery object at src mongo shell collecti
  • 将多维数组转换为单数组(Javascript)

    我有一个对象数组 来自 XLSX js 解析器 因此其长度和内容各不相同 表示已给予项目的资助 简化后 它看起来像这样 var grants id p 1 location loc 1 type A funds 5000 id p 2 lo

随机推荐