JS的apply方法详细讲解

2022-05-26 1566

apply() 方法调用一个具有给定this值的函数,以及以一个数组(或类数组对象)的形式提供的参数。

备注:call()方法的作用和 apply() 方法类似,区别就是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组

apply的一个巧妙的用处,可以将一个数组默认的转换为一个参数列表([param1,param2,param3] 转换为 param1,param2,param3) 这个如果让我们用程序来实现将数组的每一个项,来装换为参数的列表,可能都得费一会功夫,借助apply的这点特性,所以就有了以下高效率的方法:

const numbers = [5, 6, 2, 3, 7];

const max = Math.max.apply(this, numbers);

console.log(max);
// expected output: 7

const min = Math.min.apply(null, numbers);

console.log(min);
// expected output: 2

语法

func.apply(thisArg, [argsArray])

参数

  • thisArg

  • 必选的。在 func 函数运行时使用的 this 值。请注意,this可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动替换为指向全局对象,原始值会被包装。

  • argsArray

  • 可选的。一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 func 函数。如果该参数的值为 null 或  undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。浏览器兼容性 请参阅本文底部内容。



描述

在调用一个存在的函数时,你可以为其指定一个 this 对象。 this 指当前对象,也就是正在调用这个函数的对象。 使用 apply, 你可以只写一次这个方法然后在另一个对象中继承它,而不用在新对象中重复写该方法。

apply 与 call() 非常相似,不同之处在于提供参数的方式。apply 使用参数数组而不是一组参数列表。apply 可以使用数组字面量(array literal),如 fun.apply(this, ['eat', 'bananas']),或数组对象, 如  fun.apply(this, new Array('eat', 'bananas'))

你也可以使用 arguments对象作为 argsArray 参数。 arguments 是一个函数的局部变量。 它可以被用作被调用对象的所有未指定的参数。 这样,你在使用apply函数的时候就不需要知道被调用对象的所有参数。 你可以使用arguments来把所有的参数传递给被调用对象。 被调用对象接下来就负责处理这些参数。

从 ECMAScript 第5版开始,可以使用任何种类的类数组对象,就是说只要有一个 length 属性和(0..length-1)范围的整数属性。例如现在可以使用 NodeList 或一个自己定义的类似 {'length': 2, '0': 'eat', '1': 'bananas'} 形式的对象。

示例

用 apply 将数组各项添加到另一个数组

var array1 = ['a', 'b'];
var array2 = [0, 1, 2];
array1.push.apply(array1, array2);
//或者这么写 Array.prototype.push.apply(array1, array2)
console.info(array1); // ["a", "b", 0, 1, 2]

使用apply来链接构造器

你可以使用apply来链接一个对象构造器 (en-US),类似于Java。在接下来的例子中我们会创建一个全局Function 对象的construct方法 ,来使你能够在构造器中使用一个类数组对象而非参数列表。

Function.prototype.construct = function (aArgs) {
  var oNew = Object.create(this.prototype);
  this.apply(oNew, aArgs);
  return oNew;
};

备注: 上面使用的Object.create()方法相对来说比较新。另一种可选的方法,请考虑如下替代方法:

Using Object.__proto__:

Function.prototype.construct = function (aArgs) {
  var oNew = {};
  oNew.__proto__ = this.prototype;
  this.apply(oNew, aArgs);
  return oNew;
};


使用闭包:

Function.prototype.construct = function(aArgs) {
  var fConstructor = this, fNewConstr = function() {
    fConstructor.apply(this, aArgs);
  };
  fNewConstr.prototype = fConstructor.prototype;
  return new fNewConstr();
};

使用 Function 构造器:

Function.prototype.construct = function (aArgs) {
  var fNewConstr = new Function("");
  fNewConstr.prototype = this.prototype;
  var oNew = new fNewConstr();
  this.apply(oNew, aArgs);
  return oNew;
};


案例巩固

apply:方法能劫持另外一个对象的方法,继承另外一个对象的属性.

Function.apply(obj,args)方法能接收两个参数
obj:这个对象将代替Function类里this对象

args:这个是数组,它将作为参数传给Function(args-->arguments)

call:和apply的意思一样,只不过是参数列表不一样.

 Function.call(obj,[param1[,param2[,…[,paramN]]]])
obj:这个对象将代替Function类里this对象
params:这个是一个参数列表

function Person(name,age)...{   //定义一个类,人类  
    this.name=name     //名字  
    this.age=age       //年龄 
    this.sayhello=function()...{alert("hello")} 
} 
function Print()...{            //显示类的属性 
    this.funcName="Print" 
    this.show=function()...{      
        var msg=[] 
        for(var key in this)...{ 
            if (typeof(this[key])!="function") msg.push([key,":",this[key]].join("")) 
        } 
        alert(msg.join(" ")) 
    } 
} 
function Student(name,age,grade,school)...{    //学生类 
    Person.apply(this,arguments) 
    Print.apply(this,arguments) 
    this.grade=grade                  //年级 
    this.school=school                    //学校 
} 
var p1=new Person("jake",10) 
p1.sayhello() 
var s1=new Student("tom",13,6,"清华小学") 
s1.show() 
s1.sayhello() 
alert(s1.funcName)


说个两句?
精彩评论 (评论通过审核后才会显示)