ESAMScript3 给 Funciton的原型定义了两个方法:
Function.prototype.call
Function.prototype.apply
在实际开发中,特别是一些函数式风格的代码编写中,call和apply方法有为有用。
是成为一名真正的js程序员的重要知识。
1、call和apply的区别
apply接受两个参数,第一个参数指定了函数体内this对象的指向,
第二个参数为一个带下标的集合,这个集合可以为数组,也可以为类数组,
apply方法把这个集合中的元素作为参数传递给被调用的函数:
func.apply(null,[1,2,3])
call传入的参数数量不固定,跟apply相同的是,第一个参数也是代表函数体内的this指向,从第二个参数开始往后,每个参数被依次传入函数:
func.call(null,1,2,3);
当调用一个函数时,js的解释器不会计较形参和实参在数量、类型以及顺序上的区别,
js的参数在内部就是用一个数组来表示的。从这个意义说,apply比call的使用率更高,
我们不必关心具体多少参数被传入函数,只要用apply推进去就可。
call、apply 不仅仅用于指定this指向,还有其它用途,如借用其它对象的方法:
Math.max.apply(null,[1,2,4,2,34,55])
2、总结下call和apply的用途
2.1 改变this的指向
call和apply最常用于改变函数内部的this指向;
2.2 实现 Function.prototype.bind
Function.prototype.bind = function() {
let self = this //保存原函数
let context = [].shift.call(arguments) //要绑定的this上下文
let args = [].slice.call(arguments)
return function() {
return self.apply(context,[].concat.call(args,[].slice.call(arguments))) //第一个参数即obj对象
}
}
let obj = {
name : 'mengmeng'
}
let func = function(a,b,c,d){
console.log(this.name);
console.log([a,b,c,d]);
}.bind(obj,11,22,33)
func(3,4)
补充基础知识: JavaScript常用方法,https://www.runoob.com/jsref/jsref-obj-array.html
2.3 借用其它对象的方法
(function(){
Array.prototype.push.call(arguments,3);
console.log(arguments); // [1,2,3]
})(1,2);
在操作arguments的时候,我们会经常找Array.prototype借用方法。
a、把arguments转成真正的数组的时候:可以借用Array.prototype.slice() 方法;
b、想截去arguments列表中的头一个元素时,可以借用 Array.prototype.shift() 方法;
c. 借用Array.prototype.push () 时候, 确保对象的length是可读属性!
let arr = []
Array.prototype.push.call(arr,'1212') //arr 数组,对象时可以,如果是个字符串就不行了
console.log(arr);
参考书:《JavaScript设计模式与开发实践》—— 出自曾探大神。
(曾大神还是个健身达人)
书中有一段话,我非常喜欢:
Peter Norving曾说,设计模式是对语言不足的补充,如果要使用设计模式,不如去找一门更好的语言。