apply与call含义以及用法

概念:我们在写一个方法的时候,总是会用到一个关键字this,而this的指向就是我们所说的执行上下文(执行环境)
当我们需要修改this指向的时候,就可以用到apply和call。
apply接收两个参数,第一个是this的指向,第二个是调用者的参数,参数为数组。
call接收两个参数,第一个是this的指向,后面所有的都是调用者的参数。
注意:调用call和apply方法会立即执行
A.apply()、A.call()表示A的this指向window
A.apply(B)、A.call(B)表示A的this指向B
A.apply(B,[arg1,arg2])、A.call(B,arg1,arg2)表示A的this指向B,并给A传递参数arg1、arg2

apply和call可以实现继承

function Class10(){
  this.showSub = function(a,b){
        alert(a - b);
    }
}
function Class11(){
  this.showAdd = function(a,b){
        alert(a + b);
    }  
}
function Class12(){
  Class10.apply(this);
  Class11.apply(this);
}
var c2 = new Class12();
c2.showSub(3,1);    //2
c2.showAdd(3,1);    //4

一些特殊用法:

用法1:

var arr1=new Array("1","2","3");
var arr2=new Array("4","5","6");
Array.prototype.push.apply(arr1,arr2);

数组不能直接push数组,但是可以一次push很多数据push(arg1,arg2,arg3),所以此处this指向arr1,可以理解为arr1.push(arr2),arr2经过apply之后会变成一个个独立的参数,就可以达到push数组的目的了。
用法2:
Math.min.apply(null,array)
同样求一组数据的最大值和最小值,不能传入数组,只能传入一个个数据,但此时通过apply方法,就可以将apply指向一个不存在的对象,直接进行apply方法将数组转换成数据,进行比较。
用法3:
Object.prototype.toString.call(arg)
所有的对象都继承自Object,这是一个原型链,我们在使用toString会先在当前对象上寻找该方法,找不到就会进入对象的原型链上查找,直到找到原型链的顶层Object.prototype为止。但是继承自Object的所有类型基本上重写了toString方法,他们并不能进行类型的判断,只有Object的toString才能用来进行复杂数据类型的判断。此时通过call函数将this指向arg,让arg调用Object的toString方法,我们就可以判断arg的类型了。
用法4:
Array.apply(null,{length:2})
apply的第二个参数除了数组外还可以传入一个类数组对象(即包含length属性的对象),通过该方法创建的数组,所有的值都是undefined(此处不是未初始化,而是它的每个值就是undefined,等价于[undefined, undefined]),而Array(2)创建的数组就是所有的值未初始化(等价于[,])。而与Array.apply(null,{length:2})等价的还有

Array.apply(null, Array(2)); 
Array.from({length: 2});
Array(2).fill(null);

那为什么需要这样的一些写法呢?一些特殊情况下,比如map、forEach、reduce不会遍历数组中未初始化或者被delete的元素,通过以上方法创建的数组就是被初始化的数组,可用于遍历。

posted @ 2021-03-27 20:44  木-鱼  阅读(673)  评论(0编辑  收藏  举报