前置知识: this/原型/apply/call/bind
什么bind
bind是函数身上共有的方法,Fcuntion.prototype.bind,如果你了解原型应该就懂这句代码
bind不同与call与apply的是:返回一个新的函数并且指向该this,并不会直接调用
确定需求
为一个函数指定this并且返回一个新的函数,并且可以new
无废话版(es6无注释版)
function bind(newThis, ...args) {
const fn = this
function newFn(...args2) {
return fn.call(this instanceof newFn ? this : newThis, ...args, ...args2)
}
newFn.prototype = fn.prototype
return newFn
}
废话版(es5 有注释)
var slice = Array.prototype.slice
function bind(newThis) {
var bindParams = slice.call(arguments, 1)//返回bind不包含newThis的其余参数,因为第一个参数是用来绑定新的this的嘛
var fn = this //记录bind调用时的this,而this是什么取决于谁调用它,所以你能想到this就是你要修改this的那个函数吗 (这句是最难的,需要你对this了解的很清楚)
function newFn() {
var newFnParams = slice.call(arguments, 0)//这里拿到的是newFn的参数 因为参数是伪数组所以需要转成数组
return fn.apply(newFn.prototype.isPrototypeOf(this)?this:newThis,bindParams.concat(newFnParams))//看不懂就把这句注释掉,把下面4句取消注释看看
// var usedNew = newFn.prototype.isPrototypeOf(this)//如果是用了关键字这个方法会返回true
// var endThis = usedNew ? this : newThis// 如果是用了new关键字那就应该返回new中的this,要没使用就应该返回bind传进来的this
// var allParams = bindParams.concat(newFnParams) // 合并bind调用接受的参数,还有newFn调用时候的参数
// return fn.apply(endThis, allParams) //这句就不解释了,加这么多中间变量,你要看不懂,我会哭的
}
newFn.prototype = fn.prototype //确保原型地址一致
return newFn
}