思路:
- 判断调用对象是否为函数,即使我们是定义在函数的原型上的,但是可能出现使用 call 等方式调用的情况。
- 保存当前函数(调用对象)的引用,获取其余传入参数值。
- 创建一个函数返回
- 函数内部使用 apply 来绑定函数调用,需要判断函数作为构造函数的情况,这个时候需要传入当前函数的 this 给 apply 调用,其余情况都传入指定的上下文对象。
代码:
Function.prototype._bind = function (context) {
if (typeof this !== "function") {
throw new TypeError("error")
}
let args = [...arguments].slice(1)
let fn = this
return function Fn() {
// 观察一下bind执行时的环境
console.log("this:", this);
console.log("Fn:", Fn);
console.log("this instanceof Fn ->", this instanceof Fn);
// 如果说bind是作为构造函数执行,那么执行时,this指向构造出来的对象,所以使用instanceof判断
return fn.apply(
this instanceof Fn ? this : context,
args.concat(...arguments)
)
}
}
测试:
test1
// 一般情况调用时
let obj = {
name: "mikasa"
}
let user = {
getName(value) {
console.log(value);
console.log(this.name);
}
}
let userFn = user.getName._bind(obj, 666)
userFn()
this指向window,因为userFn()是在window中被调用
test2
// 绑定this,并且自带参数
function getList() {
return Array.prototype.slice.call(arguments)
}
let list = getList._bind(null, 37)
// 绑定后带上了37这个参数
console.log(list(1, 2, 3));
test3
当绑定后作为构造函数使用
var value = 2
var foo = {
value: 1
}
function bar(name, age) {
this.habit = 'shopping'; // 因为此时this指向实例obj
console.log(this.value);
console.log(name);
console.log(age);
}
var bindFoo = bar._bind(foo, 'daisy')
var obj = new bindFoo('18');
console.log(obj.habit);