先看bind是如何使用的
var id = 'window';
//定义一个函数,但是不立即执行
var test = function(){
console.log(this.id)
}
test() // window
//把test作为参数传递
var obj = {
id:'obj',
hehe:test
}
//此时test函数运行环境发生了改变
obj.hehe() // 'obj'
//为了避免这种情况,javascript里面有一个bind方法可以在函数运行之前就绑定其作用域,修改如下
var id = 'window';
var test = function(){
console.log(this.id)
}.bind(window)
var obj = {
id:'obj',
hehe:test
}
test() // window
obj.hehe() // window
拆分一下要实现的功能
- 因为bind方法不会立即执行函数,需要返回一个待执行的函数(这里用到闭包,可以返回一个函数)
return function(){}
- 作用域绑定,这里可以使用apply或者call方法来实现
xx.call(yy)/xx.apply(yy)
- 参数传递,由于参数的不确定性,需要用apply传递数组(实例更明了)
xx.apply(yy,[...Array...])
,如果用call就不太方便了,因为call后面的参数需要一个个列出来
开始吧
绑定作用域,绑定传参
Function.prototype.testBind = function(that){
var _this = this,
/*
*由于参数的不确定性,统一用arguments来处理,这里的arguments只是一个类数组对象,有length属性
*可以用数组的slice方法转化成标准格式数组,除了作用域对象that以外,
*后面的所有参数都需要作为数组参数传递
*Array.prototype.slice.apply(arguments,[1])/Array.prototype.slice.call(arguments,1)
*/
slice = Array.prototype.slice,
args = slice.apply(arguments,[1]);
//返回函数
return function(){
//apply绑定作用域,进行参数传递
return _this.apply(that,args)
}
}
动态参数
return function(){
return _this.apply(that,
args.concat(Array.prototype.slice.apply(arguments,[0]))
)
}
全部实现
Function.prototype.testBind = function(that){
var _this = this,
slice = Array.prototype.slice,
args = slice.apply(arguments,[1]);
return function(){
return _this.apply(that,
args.concat(Array.prototype.slice.apply(arguments,[0]))
)
}
}
思路很重要,思路理清楚就容易了~~
网友评论