-
作者在看到一篇优雅的使用 js 的各种方法解决算法的时候产生的疑问,到底什么时候使用 apply 和 call 啦?
-
每次看到别人用 apply 和 call 其实从以前的懵懵懂懂到现在的明白,但是自己从来未下手去用过,最近比较闲。开始打一下 JavaScript 的算法基础,刷一下简单的算法题目。然后从自己拙劣的解题思路和方法比较大牛的优雅的JavaScript的方法后有所感想。
先来看一个?栗子
Q:将数组 arr 中的元素作为调用函数 fn 的参数
这里面涉及几个知识点,函数调用的方法,apply 和 call 的使用。
- 创建函数
function argsAsArray(fn, arr) {
// code here
}
复制代码
- 输入
argsAsArray(
function (greeting, name, punctuation) {
return greeting + ', ' + name + (punctuation || '!');
}, ['Hello', 'Ellie', '!']
)
复制代码
- 输出
Hello, Ellie!
复制代码
看完上面的题目,大家知道怎么解题吗?(答案在本文最后)如果你想到了 apply 和 call,那么恭喜你,基础扎实,然后就是对 call 和 apply 的基本了解和掌握了。看下面?
怎么理解 apply 和 call
- 第一步:看看 MDN 的解释
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
- 第二步:跟着我看一个 demo
function cat(){};
cat.prototype = {
obj:"fish",
say:function(){
return "I love" + this.obj;
}
}
function doggie(){};
doggie.prototype = {
obj:"bone",
eat:function(){
return "I love" + this.obj;
}
}
function ATM(){};
ATM.prototype = {
obj:"monster",
fight:function(){
return "I love" + this.obj;
}
}
复制代码
- 上面的理解?:猫吃鱼,狗吃肉(骨头),奥特曼爱打小怪兽。
突然有一天:
- 有天狗想吃鱼了
cat.say.call(doggie,cat.obj)
//猫.吃鱼.call(狗,鱼)
//狗就吃到鱼了
复制代码
- 猫成精了,想打怪兽
ATM.fight.call(cat,ATM.obj)
//奥特曼.打小怪兽.call(猫,小怪兽)
复制代码
就这样记住了。
来训练一下实战怎么优雅(强行)的用上 apply 和 call
- Q:删除数组 arr 最后一个元素。不要直接修改数组 arr,结果返回新的数组
- 输入 : [1,2,3,4]
- 输出 : [1,2,3]
很简单对不对,不删除原来的数组,我们 clone 一个数组。然后使用 JavaScript 自带的数组方法 pop() 就行了。
- 解法一
function truncate(arr) {
var newArr = arr.slice(0);
// slice(0) 复制数组
newArr.pop();
return newArr;
}
复制代码
当然你可以优雅的使用 slice 来搞定
- 解法二
function truncate(arr) {
return arr.slice(0,-1);
}
复制代码
现在问题来了,我们要用 apply 来搞定问题咋办啦?(实现一个数组 copy)
还是创建一个新的数组,我们明白了凹凸曼和小猫小狗的用法以后,我们将 newArr 借用 [] 数组的 push 方法,对象是 arr,而达到 copy 一个数组的功能。
function truncate(arr) {
var newArr=[];
[].push.apply(newArr, arr);
newArr.pop();
return newArr;
}
复制代码
当然有很多可供实现的 apply 的使用情况,可能我这个不是很确切,大家可以鞭策一下,共同学习和理解
A(最开始题目的答案)
function argsAsArray(fn, arr) {
return fn.apply(this,arr);
}
复制代码
这里解释两个点
- 一,调用函数有几种方法?
- 直接调用: obj.func()
- call: func.call(obj,arg) // 列出参数
- apply: func.apply(obj,[a,b,c,...]) // 列出数组
- 二,call 和 apply 的区别
- 般情况下都是对象调用函数,但此处是函数调用数组对象,用call(), apply()。第一个参数是传给当前函数对象。但是call()需要将参数挨个列出,apply直接传入数组对象。