使用.call与在JavaScript中传递“this”

时间:2013-12-11 08:41:41

标签: javascript performance oop optimization

我知道如果你有一些javascript函数,并且你想调用它,那么在其中使用this将不会引用直接调用它的对象,你可以使用func.call(thatObject,param,and,more,params...)。< / p>

但假设您是func的作者,而func的唯一用法是通过func.call,
你为什么不把它定义为:

function func(that,param,and,more,params...) {
   //and in here use *that* and not *this*
}

是的,它看起来不那么“酷”,因为它不是一个物体的方法, 但是,如果func的唯一用法是通过func.call,那么它似乎只是额外的代码和开销。

我在这里遗漏了什么吗?或者我看到这种模式的源代码只是“OOed”?

3 个答案:

答案 0 :(得分:2)

似乎存在很大的性能差异。使用

func(){
  //code here, this.something
}
func.call(thatObject)
根据前几次测试,

比使用

慢约8倍
func(that){
  //code here, that.something
}
func(thatObject)

亲自测试,JSPerf here

最终,速度本身并不是我们使用的代码最重要的因素。代码是为人们设计的,就像计算机一样,我们需要清楚地向两者传达我们的意图。无论哪种代码最干净都是最好的,我们应该在可行的时候遵循惯例。我个人更喜欢这里的第二个选项,但我认为一般惯例是第一个。所以我认为你在大多数情况下使用call,除非你需要最快的代码或者约定更改。

答案 1 :(得分:0)

func.call旨在在需要提供该函数的替代(或任何)上下文时使用。

您的建议很奇怪,因为当您使用此模式定义函数时:**

function func(that,param,and,more,params...) {
   //and in here use *that* and not *this*
}

它是:

不属于任何对象

在这种情况下,传递一个对象以充当this没有任何意义,因为应该没有this.someThing调用以

开头

属于不同的对象或被定义为对象的插件

在这种情况下,完全 func.call会做什么,同时用冗余参数污染函数的定义。

更新:

以这种方式想想第二个例子 - 想象一些对象(你从同一个“类”调用的那个)允许注入任意函数,比如迭代对象的所有属性和一些摘要或者操纵或你有什么。

在Java中,常见的模式是创建Iterator并传递它,其主要目的是作为占位符,以便nexthasNext方法可以调用 - 因为Java实际上没有无对象函数。 (因为那里有一些额外的逻辑,但为了这个讨论,让我们不管它。)

JavaScript不需要这个!所有这些callapply方法都没有需要来拥有一些额外的Iterator对象来保存它们。它们可以被定义为与任何对象“分离”,同时仍然打算在一个对象的上下文中使用(因此在它们的代码中使用this)并注入到知道接受这些函数的代码中。

“主机”代码只需要callapply代码,知道this将引用自身 - 这个非常“主机”的对象。

这导致了更简洁,可重用和可移植的代码,IMO。

更新2:

查看更多here

答案 2 :(得分:0)

您的模式将适用于此方案,但一般情况下它存在一些问题......

  1. 构造函数 - &gt;我们使用新关键字创建对象,其中&#39; this&#39;对象是自动创建并返回的(默认)也有与函数原型的链接。

  2. 在调用该功能时,有人可能会忘记通过该功能&#39;对象和您的代码将失败。在调用的情况下,如果传递null,则将其重置为全局对象(非严格模式,这是常见的)