美文网首页
bind函数的js实现

bind函数的js实现

作者: 奋斗的小鸟cx | 来源:发表于2020-10-29 11:03 被阅读0次
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。

相关文章

网友评论

      本文标题:bind函数的js实现

      本文链接:https://www.haomeiwen.com/subject/ddlmwctx.html