简单版bind
bind: 绑定一个函数的上下文. (改变函数的this指向)
常见用例:
let foo = function(){
console.log(this)
}
let boo = foo.bind({content: 'hello'})
// bind只是绑定上下文,改变this,但是并不会执行,你需要自己手动执行
foo() // window
boo() // {content: 'hello'}
简单实现:
版本1
Function.prototype.bind = function(context){
var fn = this // 未改变前的this
return function(){
fn.apply(context)
}
}
然鹅, bind是可以传一个预设参数的
let foo = function(param1,param2){
console.log("hi~" + param1 + ' ' + param2)
}
let boo = foo.bind(null, '我是')
let boo1 = boo('小明') // hi~我是小明
let boo2 = boo('小花') // hi~我是小花
所以再补充一点,升级为
版本2
Function.prototype.bind = function(context,...args){
var fn = this
return function(...rest){
fn.apply(contect, [...args,...rest])
}
}
// 考虑兼容性 改用es5
Function.prototype.bind = function(){
var args = Array.prototype.slice.call(arguments)
var context = args.splice(0,1)[0]
var fn = this
return function(){
let rest = Array.prototype.slice.call(arguments)
return fn.apply(context,args.concat(rest))
}
}
升级版bind
通过简单版bind,我们熟悉了bind的作用是改变this指向,但并不会执行,需手动执行。升级版bind需要我们加深对bind的理解,可以参考mdn上bind的解释。
bind MDN
主要有以下几点
- bind会返回一个原函数的拷贝(这个拷贝也会被叫做绑定函数),并且拥有指定的this和参数
let bf = fn.bind(target, arg1, arg2,....,argn)
bf 是fn的一个拷贝,并且bf的this指向target
- 如果target是null 或者,默认window
- 如果target是普通值,对象,字符串等,则会转为其对应的包装类(Number, Object, String)
- 绑定函数具有以下内部属性: [[BoundTargetFunction]] - 包装的函数对象、[[BoundThis]]- 在调用包装函数时始终作为this值传递的值 [[BoundArguments]] - 列表,在包装函数做任何调用时,都会优先调用列表元素填充参数列表、[[Call]] - 执行与此对象关联代码。内部方法的参数是一个this值和一个参数列表。
- 绑定函数也可以使用
new
运算符构造。提供的this会被忽略,但是预设参数仍然会提供给模拟函数。
绑定函数可以使用new运算符构造 ,但是目前我们写的bind函数虽然返回了一个函数,并且这个函数除了this被指定了,其他执行的功能还和fn一致。但是,它并不能通过new构造出fn的实例对象。
测试一下
如上图所示, 既可以可以将bind绑定回module,也可实现构造函数的功能。
参考:
手写bind