Reputation: 3925
Let's take this example from The Good Parts
book:
Array.method('unshift', function () {
this.splice.apply(this,[0,0].concat(Array.prototype.slice.apply(arguments)));
return this;
});
Why did the author use this.splice
in one place and Array.prototype.slice
in other?
I tried swapping out this
and Array.prototype
with each other and got errors like the following:
TypeError: Cannot read property 'slice' of undefined
but I am still not sure about, how to know when to should use this
or Array.prototype
.
Upvotes: 5
Views: 865
Reputation: 66324
Sometimes it is easier to visualise the relationship so you realise that in many cases we have foo.bar === Foo.prototype.bar; // true
On creation of an instance foo
, the prototype property of the constructor Foo
gets set as a special reference of foo
(__proto__
), where if you try to access a property which does not exist directly on foo
the next place that property is looked for is through that reference.
This means when you expect foo
to not have been modified in a way that would hide a property from that object, it doesn't really matter whether you try to look up via foo.bar
or Foo.prototype.bar
as it is the same thing.
However, as you can see, not everything will have the same __proto__
path, so you couldn't assume obj.slice
would exist, for example. This means if you don't have an Array instance but you want to slice it, you have to reference slice through a way you know exists, such as Array.prototype.slice
Upvotes: 1
Reputation: 1074276
In the first call, this
refers to the array on which unshift
was called, and so it inherits splice
from Array.prototype
.
In the second call, though, the code uses slice
on something that isn't an array (the arguments
pseudo-array, which doesn't have a slice
method). So in that case, Crockford accessed the method via Array.prototype
.
Technically, he could have used this.slice
in the second location, like this:
Array.method('unshift', function () {
this.splice.apply(this,[0,0].concat(this.slice.apply(arguments)));
return this;
});
...but it probably would have been misleading, since the second call has nothing to do with the current array referenced by this
.
Upvotes: 9