zoukankan      html  css  js  c++  java
  • Why invoke apply instead of calling function directly?

    I think the explanation from the Mozilla Docs describes it well:

    You can assign a different this object when calling an existing function. this refers to the current object, the calling object. With apply, you can write a method once and then inherit it in another object, without having to rewrite the method for the new object.

    apply is very similar to call, except for the type of arguments it supports. You can use an arguments array instead of a named set of parameters. With apply, you can use an array literal, for example, fun.apply(this, [name, value]), or an Array object, for example, fun.apply(this, new Array(name, value)).

    As for the parameters:

    thisArg Determines the value of this inside fun. If thisArg is null or undefined, this will be the global object. Otherwise, this will be equal to Object(thisArg) (which is thisArg if thisArg is already an object, or a String, Boolean, or Number if thisArg is a primitive value of the corresponding type). Therefore, it is always true that typeof this == "object" when the function executes.

    argsArray An argument array for the object, specifying the arguments with which fun should be called, or null or undefined if no arguments should be provided to the function.

    The docs give a good example of a use case for apply. In the example below, apply is used to chain a constructor:

    function product(name, value)
    {
      this.name = name;
      if (value >= 1000)
        this.value = 999;
      else
        this.value = value;
    }
    
    function prod_dept(name, value, dept)
    {
      this.dept = dept;
      product.apply(this, arguments);
    }
    prod_dept.prototype = new product();
    
    // since 5 is less than 1000 value is set
    var cheese = new prod_dept("feta", 5, "food");
    
    // since 5000 is above 1000, value will be 999
    var car = new prod_dept("honda", 5000, "auto");
    

    Notice that in the prod_dept constructor, the this supplied refers to the prod_dept object, and arguments is an array of arguments passed to the product constructor.

    现象

    经常在网上或者阅读源码时看到下面的代码:

    Array.prototype.slice.call(arr, 3);
    

    而不是

    arr.slice(3);
    

    原因

    这是为什么呢, 毕竟下面这种方法更短, 代码看起来也更清晰.
    因为使用prototype.fn.call这种方式可以更好的复用代码, 下面这个例子:

    var divs = document.getElementsByTagName('div');
    var first_three_div = divs.slice(3) // TypeError: divs.slice is not a function
    var first_three_div = Array.prototype.slice.call(divs, 3); // ok 
    

    这里 divs 是一个 HTMLCollection 对象, 但不是一个 Array 对象, 因此直接调用 slice 会出现错误, 而使用 Array.prototype.slice.call 我们可以复用 Array 的方法实现 HTMLCollection 对象的 slice方法. 这是因为我们使用 call 调用原型方法, 使 this 指针指向 HTMLCollection 对象, 而且这个对象正好拥有 length 属性和通过数字下标获取元素的方法, 因此 slice 能够返回正确的结果.

    总结

    通过原型方法调用可以复用其他类型的方法, 比如非 Array 类型可以使用 slice 方法获得 slice 的功能.

    参考

    javascript-why-use-prototype-to-call-a-function-instead-of-just-calling-the-fun

    keep learning

  • 相关阅读:
    Entity Framework 批量操作
    Tsak多线程学习记录
    .net webservice 动态更换地址
    .NET EF Core2.0 (DBFirst)使用与配置
    MVC发布IIS后提示未配置默认文档
    未能加载文件或程序集“Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”或它的某一个依赖项。系统找不到指定的文件。
    Redis教程
    使用git将项目上传到github
    Redis集群(一)搭建Cluster模式[超简单]
    Redis 常见5大数据类型结构,附录3个数据类型
  • 原文地址:https://www.cnblogs.com/zhishaofei/p/13042685.html
Copyright © 2011-2022 走看看