在看《JavaScript高级程序设计》的时候遇到apply()和call()方法,似懂非懂,尤其是对“在特定的作用域中调用函数,实际上等于设置函数体内this对象的值”这句话不太理解,所以稍微查了些资料深入了解了一下,所以写下这篇文章,以备以后翻阅复习。
1.先附上个有意思的记忆方式,知乎原答案链接(以下修改自原答案及其评论)
猫吃鱼,狗吃肉,奥特曼打小怪兽。
有天狗想吃鱼了
猫.吃鱼.call(狗,鱼)
狗就吃到鱼了
猫成精了,想打怪兽
奥特曼.打小怪兽.apply(猫,[小怪兽1号])
如果有一天猫不仅想吃肉,还想吃猪肉牛肉羊肉,那么:狗.吃肉.apply(猫, [猪肉, 牛肉, 羊肉])
这里再配合上一个说法是: call和apply是为了动态改变this而出现的。使得可以劫持另外一个对象的方法,继承另外一个对象的属性。
2.基本理解
基本语法:
fun.apply([thisObj[,argArray]])
说明:
调用fun函数,并用thisObj对象替换fun函数里的this值,同时用argArray数组替换fun函数的参数。
3.应用
(1)扩充函数赖以运行的作用域
window.color = "red";
var o = { color : "blue" };
function sayColor() //定义为全局函数
{
alert(this.color); //所以this指向的就是window
}
sayColor(); //red
sayColor.apply(this); //red
sayColor.apply(window); //red
sayColor.apply(o); //blue,此时this指向的是对象O
//脑补一下
//var o = {
// color : "blue",
// sayColor : function(){
// alert(this.color) //当然是blue啦,因为此时this指向的是对象O
// }
//}
(2)提升程序性能
a.在Math.max()和Math.min()中的应用
先来看Math.max()和Math.min()的用法:
console.log(Math.max(5,8)); //8
console.log(Math.max(5,7,9,3,1,6)); //9
var numbers = [11,2,9,45,7,8];
console.log(Math.max(numbers)); //NaN
所以我们一般得要这样子找到一个数组中的最大值:
var numbers = [11,2,9,45,7,8];
function getMax(numArr)
{ var maxNum = numArr[0];
for(var i = 1; i < numArr.length; i++)
{
maxNum = Math.max(maxNum,numArr[i]);
}
return maxNum;
}
getMax(numbers); //45
上面这样子太低效了,然而如果我们用apply()的话就可以这样子:
function getMax2(numbers)
{
return Math.max.apply(null,numbers);//如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动指向全局对象(浏览器中就是window对象)
}
简单高效ヾ(◍°∇°◍)ノ゙
b.再举一个栗子,比如数组的push():
从这个例子可以看到,如果你想把数组c的 每一项分别作为一项 push到数组color中,把数组c作为push()的参数传进去是得不到这个效果的,它只会把 整个数组c作为一项 push到color中。所以想实现最初的需求,除了可以循环数组c每次push一项进color这个低效方法之外,可以用apply()这么做:
ps:假设用cancat()方法的话,是创建了color的副本,然后在副本上操作的,并没有作用到color本身。
c.提升程序性能这一块主要参考自AlvinXiao的js中apply使用方法小议
4.备注
(1)各种引用不当或书写谬误观点错误欢迎各位大佬指正(〃’▽’〃)
(2)欢迎交流,本人小白(:з」∠)