通过call与apply跨对象调用方法
之前讲到面向对象的番外篇的时候,我们提到过,方法是可以通过call
与apply
来进行调用的。如下所示
function sayHello(a,b){
console.log(a);
console.log(b);
console.log("你好");
}
sayHello("hello","world");
sayHello.call(window,"hello","world");
sayHello.apply(window,["hello","world"]);
call
与apply
调用方法的时候第一个参数代表调用当前的这个方法里面的this
指向性问题,我们现在给了个window
让方法里面的this
指向了全局
call
与apply
用法基本上相同,唯一不同的就是它们传递参数的方式 ,call
需要一个一个的传递,而apply
会将所有的参数变成一个数组,直接传递个数组就可以了
现在我们就使用上面的特性完成一些特殊的功能。请看下面的代码
👼 案例1,求数组元素中的最大值
var arr = [1,2,6,9,4,3,8,7];
在之前的老思维方式里面,我们可以使用“比武招亲”的这种算法思维来完成问题
var max = arr[0];
for (var i = 0; i < arr.length; i++) {
if (max < arr[i]) {
max = arr[i];
}
}
//这个时候得到的最大值是9
后面我们有一个对象叫Math
,它里面有一个方法max
,专门用于求最大值的
var max = Math.max(1,2,6,9,4,3,8,7); //得到最大值9
但是这么做,很麻烦,我们是一个数组,而你这个地方却要让我们将数组里面的元素拆出来一个一个的往里面放,这样还是不发。所以我们可以进一步的转换
我们都知道,方法除了可以使用方法名+()
来调用以外,还可以使用call
与apply
来进行调用
Math.max.call(Math,1, 2, 6, 9, 4, 3, 8, 7); //得到的最大值也是9
call
调用与apply
调用唯一的区别点就在于后面的参数,call
的参数是需要一个一个的传递的,而apply
的参数直接变成一个数组,所以我们的代码可以写成如下
// var max = Math.max.apply(Math,[1, 2, 6, 9, 4, 3, 8, 7]);
var max = Math.max.apply(Math,arr);
✈️ 案例二:将类数组转换成数组
什么是类数组,就是具备数组的特性(通过索引取值赋值,具备length属性的对象),但是又不具备数组的方法
var obj = {
0:"a",
1:"b",
2:"c",
3:"d",
4:"e",
length:5
}
请将上面的对象变成arr = ["a","b","c","d","e"]
我们可以采取之前死办法一个一个的赋值,但是这样很麻烦
分析过程:首先我们先弄清楚一下面几个点
var arr = ["a", "b", "c", "d", "e"]; var arr1 = arr.slice(); //arr在调用slice的方法,但是arr本身没有slice的方法,调用的是它的父级的方法 //arr.slice()其实就是arr.__proto__.slice()它父级的方法 //但是还要注意arr.slice()里面的this指调用者arr,但是arr.__proto__.slice()它这个方法里面的this如果指向调用者就是arr.__proto__ //所以我们需要将arr.__proro__.slice()里面的this重新指向arr //这个时候我们就使用arr.__proro__.slice.call(arr) 结果 ["a", "b", "c", "d", "e"];
经过上的推理以后,我们发现
arr.slice()
其实就相当于arr.__proto__.slice.call(arr)
;在学过对象原型继承以后,我们又知道,一个对象的
__proto__
应该等于这个对象的构造函数的prototype
arr
它是一个数组,它的构造函数就是Array
所以
arr.__proto__
其实就等于Array.prototype
arr.slice()
就应该等于arr.__proto__.slice.call(arr)
也应该等于Array.prototype.slice.call(arr)
slice
方法我们也学过,就是截取自身,返回一个新的数组
var arr = Array.prototype.slice.call(obj); //["a","b","c","d","e"]
//上面的代码就是将slice方法里面的this变成了obj这个对象 ,这样在截取的时候就是在操作obj这个对象
//操作完obj这个对象以后就返回了一个新的数组给我
上面的代码其实就是类数组转数组的方法。同学们一定要牢牢的记住
评论区