Usage and Implementation of Js_bind( ), call( )

Let's first understand bind( ) through the following example

this.num = 9; 
var mymodule = {
  num: 81,
  getNum: function() { return this.num; }
};

module.getNum(); // 81

var getNum = module.getNum;
getNum(); // 9, 因为在这个例子中,"this"指向全局对象

// 创建一个'this'绑定到module的函数
var boundGetNum = getNum.bind(module);
boundGetNum(); // 81

It can be seen bind()that there are many usage scenarios, but bind()the function was added in the fifth edition of ECMA-262; it may not work on all browsers. This requires us to implement bind()the function ourselves.

(There is also a good article about bind https://juejin.cn/post/6844903718089916429 )

First, we can simply implement the method by assigning a scope to the target function bind():


Function.prototype.bind = function(context){
  self = this;  //保存this,即调用bind方法的目标函数
  return function(){
      return self.apply(context,arguments);
  };
};

Considering the case of function currying, we can build a more robust bind():

Function.prototype.bind = function(context){
  var args = Array.prototype.slice.call(arguments, 1),
  self = this;
  return function(){
      var innerArgs = Array.prototype.slice.call(arguments);
      var finalArgs = args.concat(innerArgs);
      return self.apply(context,finalArgs);
  };
};


The bind() method this time can bind objects, and also supports passing parameters when binding.

Continuing, Javascript functions can also be used as constructors, so when the bound function is called in this way, the situation is more subtle, and the transfer of the prototype chain needs to be involved:

Function.prototype.bind = function(context){
  var args = Array.prototype.slice(arguments, 1),
  F = function(){},
  self = this,
  bound = function(){
      var innerArgs = Array.prototype.slice.call(arguments);
      var finalArgs = args.concat(innerArgs);
      return self.apply((this instanceof F ? this : context), finalArgs);
  };

  F.prototype = self.prototype;
  bound.prototype = new F();
  retrun bound;
};


This is the implementation of bind() in the book "JavaScript Web Application": By setting a transit constructor F, the bound function and the function calling bind() are on the same prototype chain, and the new operator is used to call the bound function. After defining the function, the returned object can also use instanceof normally, so this is the most rigorous bind() implementation.

In order to support the bind() function in the browser, only a slight modification of the above function is required:

Function.prototype.bind = function (oThis) {
    if (typeof this !== "function") {
      throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
    }

    var aArgs = Array.prototype.slice.call(arguments, 1), 
        fToBind = this, 
        fNOP = function () {},
        fBound = function () {
          return fToBind.apply(
              this instanceof fNOP && oThis ? this : oThis || window,
              aArgs.concat(Array.prototype.slice.call(arguments))
          );
        };

    fNOP.prototype = this.prototype;
    fBound.prototype = new fNOP();

    return fBound;
  };

 

The use and implementation of call( )

var foo = {
    value : 1
   };
   function bar(){
       console.log(this.value);
   }
   // bar.call(foo);

   //实现
  Function.prototype.call2 = function(canshu){
      canshu.fangfa = this;
      canshu.fangfa();
      delete canshu.fangfa();
   }

   bar.call2(foo);

 

Guess you like

Origin blog.csdn.net/qq_41916378/article/details/113375397