3

可能重复:
为什么是 Object.defineProperty() 而不是 this.defineProperty() (对于对象)?

我注意到特定对象的所有方法都可以从实际的对象实例中调用,即,object.method();或者通过将对象Object.method()作为参数传递给。例如:

var a = ['one', 2, 3, 'four'];
a.reverse();
// OR
Array.reverse(a);

我似乎得到了同样的行为。我想知道有什么区别,什么时候会使用另一个?

4

1 回答 1

6

Object.method(o)Object对象(Object在 JavaScript 中是一个真实的对象)上查找一个被调用的属性method,并尝试通过传入变量来调用它o。在通话期间,this将是Object

o.method()在变量引用的对象上查找被调用o的属性method并尝试调用它,而不是传入任何内容。在调用期间,this将是o.

正如你所看到的,他们做的事情完全不同。

我注意到一个特定对象的所有方法都可以从实际的对象实例中调用......或者通过将对象Object.method()作为参数传递给它。

不,他们不能。您的示例Array.reverse(a)在标准实现上失败,Array因为Array没有调用属性reverse,因此不能将其作为函数调用。编辑:您在评论中注意到它可以在 Firefox 的暂存器中使用,我刚刚验证了这一点。这意味着 Firefox 的 SpiderMonkey JavaScript 引擎正在应用一个非标准扩展,Array该扩展提供了reverse. 这是特定于 Firefox 的Array,而不是通用的所有对象。(例如,如果您自己制作Foo,它的原型函数也不会神奇地添加到其中Foo。)

使近似等效的标准a.reverse()方法是通过原型,如下所示:

Array.prototype.reverse.call(a);

确实适用于标准引擎。那么让我们看看它的作用:

  1. prototypeArray.

  2. reverse从它在#1 中获得的对象获取属性。

  3. 它利用 JavaScript 函数对象的特性调用属性引用的Function#call函数,使其成为函数调用过程中this传入的参数。call

当您创建一个数组时,该对象将获得一个底层原型。Array.prototype该原型是创建新数组时引用的对象。所以a有一个reverse属性,因为它的底层原型有一个reverse属性。

这样a.reverse()做:

  1. reversea对象中获取属性。由于(通常)a不会有自己的名为 的属性reverse,因此标准 JavaScript 属性查找会查找a的底层原型。它在那里找到属性并使用它的值。

  2. 调用该函数,使其thisa调用中。

如您所见,只要底层原型仍然引用同一个对象a,最终结果是相同的。Array.prototype(他们有可能不这样做,尽管在Array或任何其他内置的情况下,如果有人替换[而不是扩充] Array.prototype,那将是一件坏事(tm)。)

于 2012-12-16T11:20:48.203 回答