三种情况都是改变this的指向,不同的是bind返回的是一个函数
javascript
//call
let foo = {
value: 1
};
Function.prototype.call2 = function (context) {
const context2 = context || window
//this指的是要改变this函数
context2.fn = this
const args = [...arguments].slice(1)
//调用一次再删除即可
const result = context2.fn(...args)
delete context2.fn
return result
}
console.log(bar.call2(foo,'james',20));
javascript
//apply
Function.prototype.apply2 = function (context,arr=[]) {
const context2 = context || window
context2.fn = this
console.log(arr,888);
const result = context2.fn(...arr)
delete context2.fn
return result
}
console.log(bar.apply2(foo,['james',20]));
javascript
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的this
let args = [...arguments].slice(1)
let fnop = function(){}
//判断是否作为构造函数使用
let fBound = function(){
let bindArgs = [...arguments]
//this为实例对象,在实例对象中的this指向无效 指向window
return _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的指向就无效了。
javascript
//new
function Person(){}
let person = objectFactory(Person,data)
function objectFactory(){
let obj = new Object()
const Constructor = [].shift.call(arguments) //会返回第一个参数,也就是构造函数
const ret = Constructor.apply(obj,arguments) //绑定了this
obj.__proto__ = Constructor.prototype
return typeof ret === "object"?ret:obj; //判断返回值
}