从经典案例中认识call(),apply(),bind()
2019-01-25 本文已影响25人
罗坤_23333
目录
- function基础
- call(context,arg1,arg2)
- apply(context,[arg1,arg2])
- bind(context)
function基础
在ECMAScript中函数是对象,因此函数也有属性和方法。
1.属性
-
length
参数数量 -
prototype
指向函数的所有实例方法,换句话说,诸如toString()
和valueOf()
(返回函数的代码) 都保存在prototype
名下
2.方法
每个函数都包含两个非继承而来(即不在prototype
名下)的方法apply()
和call()
apply(context,[arg1,arg2,...])
apply()
方法接收两个参数:一个是在其中运行的函数作用域,另一个可以是arguments
也可以是自定义Array
的实例。
经典案例
- 获取数组中最大的值
var arr = [1,2,3,4,9,8,7,5]
var result = Math.max.apply(null,a rr)
- 使用push合并数组
var arr1 = [1,2,3]
var arr2 = [4,5,6]
Array.prototype.push.apply(arr2,arr1);
console.log(arr2) //[4,5,6,1,2,3]
- 模拟construct
构造器方法
Function.prototype.construct = function(){
var oNew = Object.create(this.prototype);
this.apply(oNew, arguments);
return oNew;
}
call(context,arg1,arg2,arg3,...)
call()
与apply()
用法相同,只是除了第一个都是作用域之外,其余参数必须逐个列举出来,即 使用call()
方法时必须明确要传多少参数,同样也可以先创建函数之后再利用call
确定参数。
经典案例
- 使用call
调用父构造函数实现继承
function Parent(name, age){
this.name = name;
this.age = age;
}
function Son(name, age, weight){
Parent.call(name, age) //继承Parent函数的name和age属性
this.weight = weight //私有属性
}
var son = new Son('Niko', 24, 140)
console.log(son) // Son {name:'Niko', age:24, weight:140}
- 使用call
调用匿名函数
const arr = [0,1,2,3,4]
for(let i=0; i<arr.length; i++){
(function(i){
//...
console.log(i) // 0,1,2,3,4
}).call(arr, i)
}
- 🔝修改上下文this
指向
var name = 'Niko'
function func(){ console.log(this.name) }
var obj = {
name : 'Bellic'
}
func.call(obj) // Bellic
func(); // Niko
bind(context)
bind()
方法会创建一个函数的实例,其this
值会被绑定传递给bind()
函数的值。
Function.prototype.bind = function(context){
var self = this; //保存原函数
return function(){ // 返回一个新函数
return self.apply( context, arguments )
}
}
总结
它们真正强大的地方是能够扩充函数赖以运行的作用域
参考
- 摘自《JavaScript高级程序设计》(第3版) p.116 函数属性和方法
- 案例参考自https://developer.mozilla.org/