Function.prototype.bind()
bind()将函数绑定到某个对象,bind()会创建一个函数,函数体内的this对象的值会被绑定到传入bind()第一个参数的值,剩余的就是其它参数类似apply传入。 例:fn.bind(obj),可以理解为obj.fn(),fn中this就指向obj;
第一版
Function.prototype.myBind = function(context, ...args1) {
let _self = this; // this指向调用的function
return function(...args2) {
return _self.apply(context, args1.concat(args2));
}
}
function test(a, b, c) {
console.log(this.value + ' ' + a + ' ' + b + ' ' + c);
}
var obj = {
value: 'ccf'
};
let hello = test.myBind(obj,1,2,3);
hello(); // ccf 1 2 3
// arguments 类数组转数组的方法
// es6
// es6 Array.from(arguments) [...arguments];
// es5 [].slice.call(arguments) 等价于Array.property.slice.call(arguments);
第二版
bind绑定后, 作为构造函数new新对象,bind的obj会丢失
let stuff = test.bind(obj,1,2,3);
stuff(); // ccf 1 2 3
new stuff(); // undefined 1 2 3
改造下
Function.prototype.myBind = function(context, ...args1) {
let _self = this; // this指向调用的function
let fn = function(...args2) {
if(this instanceof fn) {
return _self.apply(_self, args1.concat(args2));
} else {
return _self.apply(context, args1.concat(args2));
}
}
return fn
}
let hello = test.myBind(obj,1,2,3);
new Hello() // ccf 1 2 3 new操作,构造函数返回值是否是个对象,如果是对象,就返回这个对象,否则返回临时对象
hello(); // ccf 1 2 3
第三版
添加原有原型链
test.prototype.hello = 'my friend'; // 在原型链上添加一个属性
let stuff = test.bind(obj,1,2,3);
stuff(); // ccf 1 2 3
let bbq = new stuff(); // undefined 1 2 3
console.log(bbq.hello) // undefined
原有的属性值丢失
Function.prototype.myBind = function(context, ...args1) {
let _self = this; // this指向调用的function
let fn = function(...args2) {
if(this instanceof fn) {
return _self.apply(_self, args1.concat(args2));
} else {
return _self.apply(context, args1.concat(args2));
}
}
fn.prototype = _self.prototype;
return fn
}
let test = function(a,b,c) {
console.log(this.value + ' ' + a + ' ' + b + ' ' + c);
}
test.prototype.hello = 'my friend';
let hello = test.myBind({value: 'ccf'},1,2,3);
let go = new hello();
go.hello // 'my friend'
第四版
实例化的对象,可以修改原有原型链
let go = new hello();
go.hello // 'my friend'
go.__proto__.hello = 'my boy';
test.prototype.hello // 'my boy' // 修改原有构造函数的原型
Function.prototype.myBind = function(context, ...args1) {
let _self = this; // this指向调用的function
let fn = function(...args2) {
if(this instanceof fn) {
return _self.apply(_self, args1.concat(args2));
} else {
return _self.apply(context, args1.concat(args2));
}
}
fn.prototype = Object.create(_self.prototype);
//Object.create 方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__
return fn
}
收工!