bind(),apply(),call()理解

Function.prototype.call()

// call函数的签名
fun.call(thisArg, arg1, arg2, ...)
复制代码

call函数能够这样理解数组

  • 容许为不一样的对象分配和调用属于一个对象的函数/方法
  • 提供新的 this 值给当前调用的函数/方法。

参数:app

  • thisArg: 在 fun 函数运行时指定的 this 值。
  • arg1..:指定的参数列表。

call函数把某个方法的this改为了第一个参数。给该函数传入多个参数,并执行当前函数。函数

call函数有这么几个要点,须要理解:ui

  • this能够传null,能够传空,这时候this指向window
  • 函数是能够有返回值的!有返回值返回返回值,没有返回值返回undefined
/* 把函数当成对象,而后删除对应的属性值 */
    Function.prototype.call2 = function (context) {
    	// 判断当前的this对象是否为null,为空指向window
      var context = context || window;
    	// 首先要获取调用call的函数,用this能够获取
      context.fn = this;
    
      var args = [];
    	// 获取call的参数
      for(var i = 1, len = arguments.length; i < len; i++) {
          args.push('arguments[' + i + ']');
      }
    	// eval执行该函数
      var result = eval('context.fn(' + args +')');
    	// 删掉调用对象的这个属性
      delete context.fn
      return result;
    }
复制代码

Function.prototype.apply()

// apply的函数签名
func.apply(thisArg, [argsArray])
复制代码

apply函数和call函数实现的是相同的功能this

  • 容许为不一样的对象分配和调用属于一个对象的函数/方法
  • 提供新的 this 值给当前调用的函数/方法。

apply函数的参数:spa

  • thisArg: 在 fun 函数运行时指定的 this 值。
  • argsArray:指定的参数数组。

实现:prototype

Function.prototype.apply = function (context, arr) {
       // 判断当前的this对象是否为null,为空指向window
      var context = context || window;
    	// 首先要获取调用call的函数,用this能够获取
      context.fn = this;
    
      var result;
      if (!arr) {
          result = context.fn();
      }
      else {
          var args = [];
          for (var i = 0, len = arr.length; i < len; i++) {
              args.push('arr[' + i + ']');
          }
          result = eval('context.fn(' + args + ')')
      }
    
      delete context.fn
      return result;
    }
复制代码

Function.prototype.bind()

// bind函数的函数签名
function.bind(thisArg[, arg1[, arg2[, ...]]])
复制代码

bind()方法建立一个新的函数,在bind()被调用时,这个新函数的this被bind的第一个参数指定,其他的参数将做为新函数的参数供调用时使用。code

参数:对象

  • thisArg 在 fun 函数运行时指定的 this 值。
  • arg1..:指定的参数列表。

bind() 函数生成的新函数,不能本身执行,须要手动执行一下。可是这个新函数的this永远都是bind的第一个参数。继承

由于 bind 还有一个特色,就是

一个绑定函数也能使用new操做符建立对象:这种行为就像把原函数当成构造器。提供的 this 值被忽略,同时调用时的参数被提供给模拟函数。

也就是说当 bind 返回的函数做为构造函数的时候,bind 时指定的 this 值会失效,但传入的参数依然生效

实现

Function.prototype.bind2 = function (context) {
    	// 调用bind的是不是函数作一个判断
      if (typeof this !== "function") {
        throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
      }
    	// 把调用者和要传给函数的参数保存一下。
      var self = this;
    	// 获取bind2函数从第二个参数到最后一个参数
      var args = Array.prototype.slice.call(arguments, 1);
    	// 建立一个空函数来中转
      var fNOP = function () {};
    
      var fBound = function () {
          var bindArgs = Array.prototype.slice.call(arguments);
    			// 看成为构造函数时,this 指向实例,此时结果为 true,将绑定函数的 this 指向该实例,可让实例得到来自绑定函数的值
          // 以上面的是 demo 为例,若是改为 `this instanceof fBound ? null : context`,实例只是一个空对象,将 null 改为 this ,实例会具备 habit 属性
          // 看成为普通函数时,this 指向 window,此时结果为 false,将绑定函数的 this 指向 context
          return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));
      }
    	// 修改返回函数的 prototype 为绑定函数的 prototype,实例就能够继承绑定函数的原型中的值
      fNOP.prototype = this.prototype;
      fBound.prototype = new fNOP();
      return fBound;
    }
复制代码
相关文章
相关标签/搜索