var obj = {name:"Smiley"};
var greeting = function(str, lang){
this.value = 'greetingValue';
console.log("Welcome "+this.name+" to "+str+" in "+lang);
};
var objGreeting = greeting.bind(obj, 'the world');
objGreeting('JS') //Welcome Smiley to the world in JS
bind函数做了什么呢?
- 1 bind函数改变了greeting的this指向,是的this指向了obj,bind返回了一个函数objGreeing
- 2在调用bind的时候,给greeting传递参数上面的例子当中,我们把’the world’作为greeting的第一个参数。
- 3在调用objGreeting函数的时候,再传入剩余的参数。上面的例子中,第二个参数是'JS'作为第二个参数lang。
- 4bind()函数会创建一个新的函数(bound function,BF。绑定的函数也可以用new运算符构造,提供的this 会被忽略
手动写bind
Function.prototype.myBind = function() {
var thatFunc = this,
thatArg = arguments[0];
var args = Array.prototype.slice.call(arguments, 1)
if (typeof thatFunc !== 'function') {
throw new TypeError('Function.prototype.bind - ' +
'what is trying to be bound is not callable');
}
var fBound = function() {
return thatFunc.apply(this instanceof fBound
? this
: thatArg,
args.concat(Array.prototype.slice.call(arguments)));
};
var fNOP = function() {};
if (thatFunc.prototype) {
fNOP.prototype = thatFunc.prototype;
}
fBound.prototype = new fNOP();
return fBound;
}
eg
var obj = {name:"Smiley"};
var greeting = function(str, lang){
this.value = 'greetingValue';
console.log("Welcome "+this.name+" to "+str+" in "+lang);
};
Function.prototype.myBind = function() {
var thatFunc = this,
thatArg = arguments[0];
var args = Array.prototype.slice.call(arguments, 1)
if (typeof thatFunc !== 'function') {
throw new TypeError('Function.prototype.bind - ' +
'what is trying to be bound is not callable');
}
var fBound = function() {
return thatFunc.apply(this instanceof fBound
? this
: thatArg,
args.concat(Array.prototype.slice.call(arguments)));
};
var fNOP = function() {};
if (thatFunc.prototype) {
fNOP.prototype = thatFunc.prototype;
}
fBound.prototype = new fNOP();
return fBound;
}
var objGreeting = greeting.myBind(obj, 'the world');
var newObj = new objGreeting('JS');
- this instanceof fBound这句话中的this,如果是在new关键字调用情况下,会指向newObj,而newObj就是fBound的实例,this instanceof fBound就是true,我们不再使用thatArg作为greeting的this,而是直接使用newObj作为greeting的this 。而当做普通函数调用的时候,this instanceof fBound就是false,greeting中的this依然指向 thatArg。
- fBound.prototype = thatFunc.prototype;来实现。如果没有这句话,在new关键字调用下,newObj“继承”自Object;加上这句话之后,我们把fBound的prototype修改为绑定函数的prototype,这样newObj就可以“继承”自greeting了。
不过,上述代码还有一个问题,如果我们修改了fBound的prototype,greeting的prototype也会被修改。因此,我们需要一个中间变量fNOP,让它等于一个空函数,通过fNOP来维护原型关系,并让fBound.prototype与thatFunc.prototype不再指向同一个原型函数:
fNOP和greeting使用同一个prototype,而fBound.prototype实际上是fNOP的一个实例,而这个实例的proto才指向的是greeting.prototype。因此,直接修改fBound.prototype并不会修改greeting的prototype。