zoukankan      html  css  js  c++  java
  • javascript中的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) {
      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的点是:

    1. 没有搞懂“继承”的关系(现在知道是假继承)
    2. Array.prototype.push.call( arguments, 3 );为什么会这样执行,其实也就是call和apply的真正的含义。

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

    华丽谢幕!

  • 相关阅读:
    _DataStructure_C_Impl:图的邻接矩阵存储
    ios的单元測试OCUnit以及更新了之后的XCTestCase
    java之 ------ 可变參数和卫条件
    【能力提升】SQL Server常见问题介绍及高速解决建议
    NYOJ 116 士兵杀敌 (线段树,区间和)
    Spring和MyBatis环境整合
    TypeScript和JavaScript的一些小技巧记录
    VSCode配置TypeScript
    function 与 => 的区别
    Egret里用矢量挖圆形的洞
  • 原文地址:https://www.cnblogs.com/-Neo/p/15122440.html
Copyright © 2011-2022 走看看