3

Possible Duplicate:
Why is it Object.defineProperty() rather than this.defineProperty() (for objects)?

I noticed that all the methods of a particular object can be called from the actual object instance, i.e., object.method(); or by passing the object to Object.method() as an argument. For example:

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

I seemed to get the same behaviour. I was wondering what the difference was and when one would be used over the other?

Community
  • 1
  • 1
bqui56
  • 2,091
  • 8
  • 22
  • 40
  • related: [Why is it Object.defineProperty() rather than this.defineProperty() (for objects)?](http://stackoverflow.com/questions/13239317/why-is-it-object-defineproperty-rather-than-this-defineproperty-for-objects) – Bergi Dec 16 '12 at 11:51

1 Answers1

6

Object.method(o) looks on the Object object (Object is a real object in JavaScript) for a property called method and tries to call it passing in the variable o. During the call, this will be Object.

o.method() looks on the object referenced by the variable o for a property called method and tries to call it, not passing anything in. During the call, this will be o.

As you can see, they do quite different things.

I noticed that all the methods of a particular object can be called from the actual object instance...or by passing the object to Object.method() as an argument.

No, they cannot. Your example Array.reverse(a) fails on a standard implementation of Array because Array doesn't have a property called reverse and so it can't be called as a function. Edit: You note in the comments that it works in Firefox's scratchpad, and I just verified that. That means Firefox's SpiderMonkey JavaScript engine is applying a non-standard extension to Array which provides a static implementation of reverse. That's specific to Firefox's Array, not general to all objects. (If you make your own Foo, for instance, its prototype functions don't magically get added to Foo as well.)

The standard way to make the near-equivalent to a.reverse() would be via the prototype, like this:

Array.prototype.reverse.call(a);

That does work in standard engines. So let's look at what it does:

  1. It gets the prototype property from Array.

  2. It gets the reverse property from the object it got in #1.

  3. It calls the function that property referenced using the Function#call feature of JavaScript function objects to make this be the argument you pass into call during the course of the function call.

When you create an array, the object gets an underlying prototype. That prototype is the object referenced by Array.prototype when the new array is created. So a has a reverse property because its underlying prototype has a reverse property.

Doing a.reverse() does this:

  1. Gets the reverse property from the a object. Since (normally) a won't have its own property called reverse, standard JavaScript property lookup looks to a's underlying prototype. It finds the property there and uses its value.

  2. Calls that function such that this is a within the call.

As you can see, the end result is the same provided that the underlying prototype of a and Array.prototype still refer to the same object. (It's possible for them not to, although in the case of Array or any other built-in, if someone replaced [as opposed to augmenting] Array.prototype, that would be a Bad Thing(tm).)

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • `Array.reverse(a)` works in firefox scratchpad for some reason (using `Ctrl+l` for the output). – bqui56 Dec 16 '12 at 11:27
  • 1
    @stariz77: Very interesting (and I've verified it at this end). That would be Firefox doing something non-standard, I've updated the answer. – T.J. Crowder Dec 16 '12 at 11:31
  • @stariz77: BTW, I've verified that Firefox's `Array.reverse` and `Array.prototype.reverse` don't call each other. I proved it by first overriding `Array.prototype.reverse` and noting that `Array.reverse` still did the reversal, and then overriding `Array.reverse` and seeing that `Array.prototype.reverse` still did the reversal. I expect they each call an internal function to reverse the array. Thanks for the info about Firefox, I never knew that. – T.J. Crowder Dec 16 '12 at 11:58