Function.prototype.myBind = function(context,...args1){
const _this = this
return function(...args2){
return _this.apply(context,[...args1,...args2]);
}
}
const student ={
name: "mio"
}
function log(...values) {
console.log(`${this.name} call ${values.join()}`)
}
const log_bind = log.myBind(student,'yui','lzu')
log_bind('mio')
这里是如何利用剩余参数的
这段手写 bind 里,用到了两次剩余参数:
Function.prototype.myBind = function(context, ...args1) {
return function(...args2) {
return _this.apply(context, [...args1, ...args2])
}
}第一次:...args1
function(context, ...args1)这里的 args1 用来接收绑定时就提前传入的参数。
比如:
const log_bind = log.myBind(student, "yui", "lzu")这时:
args1 // ["yui", "lzu"]也就是说,bind 在创建新函数的时候,就先把一部分参数保存起来了。
第二次:...args2
return function(...args2)这里的 args2 用来接收真正调用新函数时传入的参数。
比如:
log_bind("mio")这时:
args2 // ["mio"]最后再把两部分参数拼起来
[...args1, ...args2]这里不是剩余参数了,而是扩展运算符。它的作用是把两个数组展开后重新合并成一个新数组。
结果就是:
["yui", "lzu", "mio"]然后再交给:
_this.apply(context, [...args1, ...args2])这样原函数执行时,就同时拿到了:
- 绑定时预存的参数
- 调用时后来补上的参数
这其实就是“参数预置”
bind 除了固定 this,还会把一部分参数先记住,这就是常说的偏函数效果。
所以这段代码本质上做了两件事:
- 固定
this为context - 通过
...args1和...args2实现参数分两次传递,最后再合并
一句话理解
...args1 负责收集“绑定时的参数”,...args2 负责收集“调用时的参数”,最后用 [...args1, ...args2] 把它们拼起来交给原函数。