Function.prototype.apply() & Function.prototype.call()
官方描述
apply()
方法在指定this
值和参数(参数以数组或类数组对象的形式存在)的情况下调用某个函数。fun.apply(thisArg[, argsArray])
call()
方法在使用一个指定的this
值和若干个指定的参数值的前提下调用某个函数或方法。fun.call(thisArg[, arg1[, arg2[, ...]]])
两者基本一致,只有一个区别,就是
call()
方法接受的是若干个参数的列表,而apply()
方法接受的是一个包含多个参数的数组。
注意点thisArg
: 在 fun
函数运行时指定的 this
值。需要注意的是,指定的 this
值并不一定是该函数执行时真正的 this 值,如果这个函数处于非严格模式下
,则指定为 null
或 undefined
时会自动指向全局对象(浏览器中就是window
对象,说明thisArg
可以不传),同时值为原始值(数字,字符串,布尔值)的 this
会指向该原始值的自动包装对象(Number,String,Boolean
)。
温故
以call
为例,apply
把后面参数转化成数组格式即可
-
在调用一个存在的函数时,为其指定一个全新的 this 对象(原函数的this对象
此次调用
被覆盖),并且可以传递参数,function test(a) { console.log(this.one); console.log(a) } test.call({one:1},2) // 1 // 2 //我们在test函数执行的时候绑定一个对象 {one:1} 和参数 2
-
调用父构造函数,实现继承
function a(a) { this.a = a } function b(b) { this.b = b } //想要创建一个实例对象拥有a和b里面的属性 function c(a,b){ //相当于a,b函数执行了一次,所以属性会被创建 a.call(this,a) b.call(this,b) } //效果等同于 function c(a,b){ this.a = a; this.b = b } var d = new c(1,2); d会同时用于a,b的属性,这样在涉及到很多属性继承时候就很方便 //c {a: 1, b: 1}
使用call方法调用匿名函数,引用官方示例,其实和1类似
var animals = [
{species: 'Lion', name: 'King'},
{species: 'Whale', name: 'Fail'}
];
for (var i = 0; i < animals.length; i++) {
(function (i) {
this.print = function () {
console.log('#' + i + ' ' + this.species + ': ' + this.name);
}
this.print();
}).call(animals[i], i);
}
// #0 Lion: King
// #1 Whale: Fail
知新(for me)
由于call
方法需要穷举所有需要传递的参数,所以只能在已知参数的情况下使用,apply
则零活很多,但是接收参数的情况是一样的,apply可以将数组形式默认转化成一个参数列表 参数[a,b,c]会以(a,b,c)
的形式接收。
举例来说:
//比较一组数据大小
Math.max(9,2,4,6,7) // 9
Math.max([9,2,4,6,7]) // NaN
//因为Math.max 方法不能接收一个数组 ,所以我们可以进行遍历
var arr = [9,2,4,6,7],arr_len = arr.length,maxNumber = arr[0];
for(var i = 1 ;i< arr_len ;i++){
maxNumber = Math.max(maxNumber,arr[i])
}
maxNumber // 9
//这样能够达到效果,但是可以有更方便高效的方法:用apply进行改造
Math.max.apply(null,[9,2,4,6,7]) //9
//经过apply转化,Math.max此次执行的时候真正接收的参数是 (9,2,4,6,7)
//所以类似这种本来需要写成遍历数组变量的任务 ,都可以用apply执行,Array.prototype.push也是
还有个 bind方法和这两个很类似,可以参考另一篇内容,详细说了bind方法
javascript原生一步步实现bind分析
以上是个人理解,如果有误,感谢指导!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。