三种情况都是改变this的指向,不同的是bind返回的是一个函数
//call
let foo = {value: 1
};Function.prototype.call2 = function (context) {const context2 = context || window//this指的是要改变this函数context2.fn = thisconst args = [...arguments].slice(1)//调用一次再删除即可const result = context2.fn(...args)delete context2.fnreturn result
}console.log(bar.call2(foo,'james',20));
//apply
Function.prototype.apply2 = function (context,arr=[]) {const context2 = context || windowcontext2.fn = thisconsole.log(arr,888);const result = context2.fn(...arr)delete context2.fnreturn result
}console.log(bar.apply2(foo,['james',20]));
var value = 2;var foo = {value: 1
};function bar(name, age) {this.habit = 'shopping';console.log(this.value);console.log(name);console.log(age);
}bar.prototype.friend = 'kevin';var bindFoo = bar.bind(foo, 'daisy');var obj = new bindFoo('18');
// undefined
// daisy
// 18
console.log(obj.habit);
console.log(obj.friend);
// shopping
// kevin//bind
function bar3() {console.log(this.value);
}
Function.prototype.bind2 = function (context) {if(typeof this !== 'function'){throw new Error("this is not a function")}let _this = this //此处获取的是指向bar的thislet args = [...arguments].slice(1)let fnop = function(){}//判断是否作为构造函数使用let fBound = function(){let bindArgs = [...arguments]//this为实例对象,在实例对象中的this指向无效 指向windowreturn _this.apply(this instanceof fnop?this:context,[...args, ...bindArgs])}fnop.prototype = this.prototype//获取原型对象,继承原型对象的属性fBound.prototype = new fnop() //防止一同修改this的原型对象,使用fnop作为中间站return fBound
}const bindFn = bar3.bind2(foo)
bindFn()
如果bind返回的参数 作为构造函数使用,那么这个this的指向就无效了。
//newfunction Person(){}
let person = objectFactory(Person,data)
function objectFactory(){let obj = new Object()const Constructor = [].shift.call(arguments) //会返回第一个参数,也就是构造函数const ret = Constructor.apply(obj,arguments) //绑定了thisobj.__proto__ = Constructor.prototypereturn typeof ret === "object"?ret:obj; //判断返回值
}