Loading

js中call和apply继承和借用方法

起因

Array.prototype.push.call( arguments, 3 );当你看到这句代码时有没有同我一样感到疑惑这句代码到底是什么意思?

PS:call和apply使用的场景有很多这里目前只是介绍其中的一部分

第一种:继承

利用mdn上的例子

function Product(name, price) {
  this.name = name;
  this.price = price;
}

function Food(name, price) {
  // 相当于调用“super”构造函数
  Product.call(this, name, price);
  this.category = 'food';
}

// 上面的函数等价于这个函数
// function Food(name, price) {
//   this.name = name;
//   this.price = price;
//   this.category = 'food';
// }

console.log(new Food('cheese', 5).name);

Product的构造函数是:

function Product(name, price) {
  this.name = name;
  this.price = price;
}

Product.call(this, name, price);是吧Product的构造函数放在了Food函数的中,有了类似“继承”的效果。
可以在浏览器中console中测试一下:

> let a = new Food('cheese', 5)
> a
< Food {name: "cheese", price: 5, category: "food"}
    category: "food"
    name: "cheese"
    price: 5
    __proto__:
      constructor: ƒ Food(name, price)
      __proto__: Object

a的__proto__并没有变化,但在Food函数中多了name和price两个属性,所以才说类似“继承”。

第二种:借用方法

我们再说回上面的例子Array.prototype.push.call( arguments, 3 );其实是借用了Array.prototype.push的方法使arguments对象有了类似array的push功能,为什么可以这样使用呢?首先我们来看v8中array的push功能的代码:

function ArrayPush() {
  var n = TO_UINT32( this.length );    // 被push的对象的length
  var m = %_ArgumentsLength();     // push的参数个数
  for (var i = 0; i < m; i++) {
    this[ i + n ] = %_Arguments( i );   // 复制元素     (1)
  }
  this.length = n + m;      // 修正length属性的值    (2)
  return this.length;
};

假如let arguments = {}(PS:IE中必须显示生命lengthlet arguments = { length: 0 })arguments是这个对象上面的函数也能正常运行,所以不管对象是否是array都可以使用ArrayPush函数但需要满足(1)和(2)处的条件否则会报错。

var a = {};
Array.prototype.push.call( a, 'first' );

alert ( a.length );    // 输出:1
alert ( a[ 0 ] );    // first

其实call和apply还有一个功能是可以改变this的指向,想必大家在了解this的时候就已经知道这一点了,这里就不展开讲了。

华丽谢幕!

posted @ 2021-08-10 10:21  _尼欧`  阅读(132)  评论(0编辑  收藏  举报