用法 :
let obj={
name:'我'
}
function fn(country,type){
console.log(this.name+'是'+country+type);
}
let newFn=fn.bind(obj,'中国');
newFn('人');
打印结果:我是中国人.
我们可以得出结论:
- bind也可以改变this,但是他不会立即执行,而是返回一个函数(高阶函数),我们需要再次执行这个绑定后的函数才能拿到结果;
- 我们在绑定this的时候,还可以传递参数,第一个参数是this指向,从第一个参数之后的参数就是对应函数的形参,执行返回的函数也可以传递参数。
先来实现第1个特点---改变this指向,并返回一个函数:
Function.prototype.mybind=function(context){
let fn=this;//先保存需要执行的函数
return function(){
fn.apply(context);//让原函数执行并通过apply改变this指向
}
}
再来实现第2个特点---可以分次传入参数:
Function.prototype.mybind=function(context){
let fn=this;//先保存需要执行的函数
let binArgs=[].slice.call(arguments,1);//获取绑定this指向时的参数
return function(){
let reargs=[].slice.call(arguments);//获取调用绑定this后函数的参数
fn.apply(context,binArgs.concat(reargs));//让原函数执行并通过apply改变this指向,合并两次传递的参数
}
}
另外,bind还有一个特点:调用完bind后返回的函数,还可以把这个函数当成一个类来调用. 用法:
let obj={
name:'我'
}
function fn(country,type){
this.name='你'
}
fn.prototype.city='北京'
let newFn=fn.bind(obj)
let oBind= new newFn();
console.log(oBind);
console.log(oBind.city);
结果打印出: fn {name: "你"} 北京 我们可以得出结论:
- 被new之后bind函数的this并没有改变,且返回的实例会继承构造函数的构造器属性与原型属性
最后实现第3个特点---当作构造函数new之后,不改变this指向,并让返回的函数原型指向构造函数的原型
增加判断
if(this instanceof fBound){
fn.apply(this,binArgs.concat(args));
}else{
fn.apply(context,binArgs.concat(args));
}
并让返回的函数原型指向构造函数的原型
fBound.prototype=this.prototype;
代码整合后:
Function.prototype.mybind=function(context){
let fn=this;
let binArgs=[].slice.call(arguments,1)
function fBound(){
let reargs=[].slice.call(arguments)
if(this instanceof fBound){
fn.apply(this,binArgs.concat(reargs));
}else{
fn.apply(context,binArgs.concat(reargs));
}
}
fBound.prototype=this.prototype
return fBound
}