zoukankan      html  css  js  c++  java
  • 原生javascript实现call、apply和bind的方法

    var context = {id: 12};
    function fun (name, age) {
      console.log(this.id, name, age)
    }

    bind

    bind() 方法会创建一个新函数。当这个新函数被调用时,bind() 的第一个参数将作为它运行时的 this,之后的一序列参数将会在传递的实参前传入作为它的参数。

     原生 bind
    1. var a = fun.bind(context, 'bind');
    2. a(1); // 12, 'bind', 1  :作为普通函数
    3. new a('1'); // undefined, 'bind', '1'  :作为构造函数

    以上例子可以看出

         bind作为普通函数使用时,改变的this的指向,指向context对象;fun函数执行了;传入参数不确定,可以在第一步bind传值,也可以在第二步执行函数fun传值。

         bind最为构造函数使用时,不同点是this指向实例的对象。

    bind的实现代码

    Function.prototype.mybind = function (context) {
      if (this && this.constructor !== Function) // 抛错
        throw new Error("Function.prototype.mybind - what is trying to be bound is not callable");
      // this =>绑定函数 fun
      var self = this;
    // 获取mybind函数从第二个参数到最后一个参数 var arg = Array.prototype.slice.call(arguments, 1); function fbound() { // 普通函数: this => window 构造函数: this => 实例对象
    // 获取mybind返回函数传入的函数 var args = Array.prototype.slice.call(arguments); self.apply(this instanceof self ? this : context, arg.concat(args)); } var FNOP = function () {}; FNOP.prototype = this.prototype; fbound.prototype = FNOP.prototype; return fbound; } var a = fun.mybind(context, 'mybind'); a('12') // a: 普通函数 var b = new a(12) // a: 构造函数 b: 实例对象

      兼容写法

    Function.prototype.bind = Function.prototype.bind || function () {
        ……
    };

    call

      call() 方法在使用一个指定的 this 值和若干个指定的参数值的前提下调用某个函数或方法。

       原生 call
    1. fun.call(context, 'call', 2) // 12, call, 2
    

      

    call 的实现代码

    Function.prototype.mycall = function (context) {
      if (this && this.constructor !== Function)
        throw new Error(this.name + ".mycall is not a function");
      context = context || window;
      context.fn = this;
      var arg = [];
      for (var i =1; i< arguments.length; i++) {
        arg.push('arguments[' + i + ']');
      }
      eval('context.fn(' + arg + ')');
      delete context.fn;
    }
    
    fun.mycall(context, 'mycall', 3);  // 12, 'mycall', 3
    

      

    apply

      apply与call的实现原理差不多,只是apply第二个参数是数组;

    1. fun.apply(context, ['call', '4']) // 12, call, '4'
    

      

    Function.prototype.myapply = function (context, arr) {
      if (this && this.constructor !== Function)
        throw new Error(this.name + ".myapply is not a function");
      context = context || window;
      context.fn = this;
      var arrs = [];
      if (arr && arr.constructor === Array) { // 判断第二个参数是数组类型
        for (var i =0; i <arr.length; i++) {
          arrs.push('arr[' + i + ']');
        }
        eval('context.fn(' + arrs + ')');
      } else if (!arr) { // 第二个参数不传
        delete context.fn();
      } else { // 第二个参数不是数组类型
        throw new Error ("CreateListFromArrayLike called on non-object");
      }
      delete context.fn;
    }
    
    fun.myapply(context, ['myapply', 4]); 
    

      
























  • 相关阅读:
    OpenCV 图像二值化 threshold
    C++ pow()函数
    Marr-Hildreth 边缘检测 OpenCV C++实现
    OpenCV 边缘检测 Canny
    OpenCV Canny()函数
    OpenCV Sobel()函数
    OpenCV 边缘检测 Sobel
    OpenCV 边缘检测 Laplacian
    OpenCV 边缘检测 Scharr
    OpenCV 形态学变换 morphologyEx函数
  • 原文地址:https://www.cnblogs.com/weblff/p/9718321.html
Copyright © 2011-2022 走看看