思路:
- 判断调用对象是否为函数,即使我们是定义在函数的原型上的,但是可能出现使用 call 等方式调用的情况。
- 保存当前函数(调用对象)的引用,获取其余传入参数值。
- 创建一个函数返回
- 函数内部使用 apply 来绑定函数调用,需要判断函数作为构造函数的情况,这个时候需要传入当前函数的 this 给 apply 调用,其余情况都传入指定的上下文对象。
代码:
Function.prototype._bind = function (context) {if (typeof this !== "function") {throw new TypeError("error")}let args = [...arguments].slice(1)let fn = thisreturn 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 = 2var foo = {value: 1}function bar(name, age) {this.habit = 'shopping'; // 因为此时this指向实例objconsole.log(this.value);console.log(name);console.log(age);}var bindFoo = bar._bind(foo, 'daisy')var obj = new bindFoo('18');console.log(obj.habit);

