bind,call,apply在实际项目中什么地方会用到 ?

经常看到介绍call或者apply的文章,然后会以下面这种代码来举例说明 .

function identify() {
  console.log("Hello,I'm " + this.name);
}
let me = {
  name: "Kyle"
};
let you = {
  name: "Reader"
};
identify.call(me); // Hello,I'm Kyle
identify.call(you); // Hello,I'm Reader

我有点不理解的是,实际开发的时候以参数的形式传给 indentify(obj) 方法不是更好吗,

// 传参形式
function identify(obj) {
  console.log("Hello,I'm " + obj.name);
}
let me = {
  name: "Kyle"
};
let you = {
  name: "Reader"
};
identify(me); // Hello,I'm Kyle
identify(you); // Hello,I'm Reader

那么bind,call,apply一般在实际项目中什么地方会用到 ?

阅读 4k
6 个回答

我也同意第二种方法更好。实际上我觉得JavaScript没给this一个正式的形参地位就是设计失误,其他函数式/面向对象混合的语言都显式给出了(以至于被Python点名嘲讽,新语言都不敢用this这个关键字了),TypeScript如果在class之外引用this也是要求作为第一个形参显式声明的。编译器知道this是隐藏参数,程序员也知道,但大家都闷声大发财,这是最糟糕的。

bind/call/apply干什么用的

bind可以拿来做偏函数应用,试试往后面继续填参数,这些参数会被“记住”,以便之后使用。

在现代语境下,call/apply的唯一作用就是把本来是隐藏参数的this提成正式参数,允许程序员显式指定。上面举的例子Math.max.apply(null, [1, 2, 3, 4]),推荐的做法应该是Math.max(...[1, 2, 3, 4]),清晰明了,而且在现代浏览器里性能会略有提升。除非是引用了别人的代码,恕我直言,自愿去搅和call/apply的,都是文明用语行为

封装起来给别人使用/别人写的代码

个人观察,现在的大趋势也是不做文明用语行为,不在class以外乱搞this,所以可以期待别人写的代码里需要call/apply的也会越来越少。koa 1用this传上下文被喷了,koa 2马上改成显式形参。lodash这种工具库全是第二种方式传参的,如果想链式调用,都需要手动包装。

vue一大堆this,其实一小撮人是有意见的,考虑到一般来说组件的函数都不通用,不存在需要call/apply的场合,我也就接受了。但vuex的mutations很有可能是通用的,所以也是用的第二种方式传参,要不然真的是超级文明用语。如果是自己写的代码需要别人提供this,建议反思一下。

unbound

上面有回答提到“反柯里化的实现”(实际上我觉得应该叫debound),更多是历史遗留问题的妥协方案。被设计为通用的函数,本身就不应该被绑在特定的类里面,只不过此事已经发生,ES标准又不能大改,只能将就着。像Python这种兼容性喂狗的语言,早就彻底消除了“反柯里化”这种行为的必要性,全是直接用第二种方式传参。不是因为this的话,没有必要自找麻烦。

总结

  • call/apply是历史遗留问题的解决方案
  • bind的用处更广泛些,偏函数应用还是相当好使的
  • 为了用那些老库,学习call/apply还是有必要的
  • 自己写的代码不要牵扯call/apply
新手上路,请多包涵

个人觉得,在自己写代码的时候很少会用到,但是对于封装起来给别人使用的时候会用到

主要还是和this有关
上面那个 identify写的代码 你可以改传参方式 但如果是别人写的代码 第三方的插件呢

只能说这个例子只是为了更清晰的理解callapply罢了。
实际上callapply更多的会用于做一些反柯里化的实现(之前写过的一篇讲解柯里化与反柯里化)。

Array.prototype.forEach.call({
  0: 1,
  1: 2,
  length: 2
}, (item, index) => {
  console.log(item, index)
})

Math.max.apply(null, [1, 2, 3, 4])

如果你看过一些源码 你会看到这些东西 你会理解这些的含义 实际开发你可能会需要这样的用法但是你如果不知道你不会这样去用

写js插件或者包的时候,大部分都是面向对象编程,这个时候this就会很重要了,但有时候this会丢失,就可以使用call这些方法了。一个简单的js插件

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题