this.apply method with this as parameter

2019-09-08 11:25发布

问题:

On Douglas Crockford's book The Good Parts, he implements the array push method on this way:

Array.prototype.push = function ( ) {
  this.splice.apply(
    this,
    [ this.length, 0 ].
      concat(Array.prototype.slice.apply(arguments))
  );
  return this.length;
};

Dont get it how works this.method_name.apply with itself (this) as parameter, in the code corresponds to this.splice.apply; if I use Array.prototype.splice.apply I don't get the correct result.

Hope somebody may explain me which is the difference here between this.splice.apply(this, parameters) and Array.prototype.splice.apply(this, parameters)

回答1:

short answer: this.splice.apply and Array.prototype.splice are the same exact function. The "only" difference is the context in which the function is used. this.splice uses the instance of your array as the value for this and Array.prototype.splice uses Array.prototype as the value for this which is why you need to invoke it with .apply in the latter case. This way, you're telling the function what to use as this when it's run.

the ugly truth: inside the function definition this does not refer to the object Array.prototype, but instead this refers to the object (in this case an array) which is an instance of Array. Because the object is an instance of Array, means that it inherits all properties defined on Array.prototype. Array.prototype.slice is defined on Array.prototype and so it's an instance method of your object, therefore you can invoke it using this.slice. When you call slice in this manner, this refers to your object, which again is an array. When you refer to slice with Array.prototype.slice then this refers to Array.prototype in this context, which is why you need to invoke it with .apply(arguments) which says "run this function and use this=arguments".