简体   繁体   English

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

[英]using .call vs. passing “this” in JavaScript

I know that if you have some javascript function and you want to call it such that using this within it would refer not to the object on which it was directly called you can use func.call(thatObject,param,and,more,params...) . 我知道,如果你有一些JavaScript函数,你怎么称呼它使得使用this内它不会是指在其上直接叫你可以使用对象func.call(thatObject,param,and,more,params...)

But suppose you are the writer of func and the only usage for func is via func.call, 但是假设您是func的作者,并且func的唯一用法是通过func.call,
Why would you not define it to begin with as: 为什么不将其定义为:

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

yep, it looks less "cool" because its not a method of an object, but hey if the only usage for func is via func.call it all seems like just extra code and overhead. 是的,它看起来不那么“酷”,因为它不是对象的方法,但是,嘿,如果func的唯一用法是通过func.call,那一切似乎都只是多余的代码和开销。

Am I missing something here? 我在这里想念什么吗? or is the source code in which I have seen this pattern just "over OOed" ? 还是我看到这种模式的源代码只是“超过OOed”?

There appears to be a large performance difference. 似乎存在很大的性能差异。 Using 运用

func(){
  //code here, this.something
}
func.call(thatObject)

according to the first couple of tests is about 8 times slower than using 根据前几次测试,速度大约比使用速度慢8倍

func(that){
  //code here, that.something
}
func(thatObject)

Test it yourself, JSPerf here 自己测试一下, JSPerf在这里

Ultimately though, speed alone is rarely the most important factor in which code we use. 最终,尽管如此,速度最终并不是我们使用代码的最重要因素。 Code is designed for people as much as it is for computers, we need to communicate our intentions clearly to both. 代码是为人们设计的,就像为计算机设计的一样,我们需要向双方明确传达我们的意图。 Whichever makes the code cleanest is best, and we should follow conventions whenever it is feasible. 以使代码最干净的方式为最佳,并且在可行时都应遵循约定。 I personally prefer the second option here, but I think the general convention is the first. 我个人比较喜欢这里的第二种选择,但我认为一般惯例是第一种。 So I think you use call in most situations, except for when you need the fastest code possible or if the convention changes. 因此,我认为您在大多数情况下都可以使用call ,除非您需要最快的代码或约定有所更改。

func.call is intended to be used when an alternative (or any) context for the function is needed to be provided. 当需要为函数提供替代(或任何)上下文时,应使用func.call

Your suggestion is odd, since, when you define the function using this pattern:** 您的建议很奇怪,因为当您使用以下模式定义函数时:**

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

it's either: 可能是:

doesn't belong to any object 不属于任何对象

in which case passing an object to act as this doesn't make any sense, since there should be no this.someThing calls to begin with 在这种情况下传递对象来充当this没有任何意义,因为应该没有this.someThing调用开始

or belongs to a different object or is defined to be a plug to an object 属于另一个对象或被定义为对象的插件

in which case it does exactly what func.call would do, while contaminating the definition of the function with redundant parameter. 在这种情况下,它到底是什么func.call会做,而污染与冗余参数的函数的定义。

UPDATE: 更新:

Think of the second example in this way - imagine that some set of Objects (what you'd call from the same "class") allow injection of arbitraty functions, say for iteration over all properties of the object and some summary or manipulation or what have you. 考虑这种方式的第二个示例-假设某个对象集(您将在同一“类”中调用的对象)允许注入仲裁函数,例如针对该对象的所有属性进行迭代以及一些汇总或操作,或者有你。

In Java, the common pattern is to create an Iterator and pass it, and its main purpose is to serve as sort of placeholder so that next and hasNext methods can be called - since Java doesn't really have object-less functions. 在Java中,常见的模式是创建一个Iterator并将其传递, 它的主要目的是充当一种占位符,以便可以调用nexthasNext方法-因为Java实际上并不具有无对象的功能。 (granted there is some additional logic there, but let's leave it alone for the sake of this discussion). (当然,这里还有一些其他逻辑,但是为了讨论起见,我们不要理会它)。

JavaScript does not neeed this! JavaScript对此不满意! All these call and apply methods do not need to have some additional Iterator object to hold them. 所有这些callapply方法都不需要具有其他Iterator对象来保存它们。 They can be defined "detached" from any object, while still with intention to be used in a context of one (hence this usage in their code) and injected into code that knows to accept such functions. 可以将它们定义为与任何对象“分离”,同时仍打算在一个对象的上下文中使用它们(因此在其代码中使用this用法),然后将其注入知道可以接受此类功能的代码中。

The "host" code than only needs to call or apply them, knowing that this will refer to itself - this very "host" object. “主机”代码只需要callapply它们,就知道this将指向自身-这个非常“主机”的对象。

This leads to a more concise, reusable and portable code, IMO. 这导致了更简洁,可重用和可移植的代码IMO。

UPDATE 2: 更新2:

See more here . 在这里查看更多。

Your pattern will work in this scenario but in general it has some problems ... 您的模式可以在这种情况下工作,但通常会有一些问题...

  1. Constructor functions -> We create objects by using new keyword where 'this' object is automatically created and returned (default) also has the link with the function's prototype. 构造函数->我们使用new关键字创建对象,其中“ this”对象是自动创建并返回的(默认)也具有与函数原型的链接。

  2. When calling the function someone might forget to pass 'that' object and your code will fail. 调用该函数时,可能会忘记传递“那个”对象,并且您的代码将失败。 In case of call if you pass null it is reset to global object (non-strict mode which is common) 在调用的情况下,如果传递null,它将重置为全局对象(常见的非严格模式)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM