zoukankan      html  css  js  c++  java
  • 【前端基础系列】理解bind方法使用与实现

    方法描述

    bind()方法创建一个新函数,当被调用时,将其this关键字设置为提供的值。

    语法说明

    fn.bind(thisArg,arg1,arg2,..)

    参数说明

    thisArg:当绑定函数被调用时,该参数会作为原函数运行时的this指向。当使用new操作符调用绑定函数时,该参数无效。
    arg1,arg2,…:当绑定函数被调用时,这些参数将传递给被绑定的方法。

    应用场景

    1、创建绑定方法

    this.x = 9; 
    var module = {
      x: 81,
      getX: function() { return this.x; }
    };
    
    module.getX(); // 返回 81
    
    var retrieveX = module.getX;
    retrieveX(); // 返回 9, 在这种情况下,"this"指向全局作用域
    
    // 创建一个新函数,将"this"绑定到module对象
    // 新手可能会被全局的x变量和module里的属性x所迷惑
    var boundGetX = retrieveX.bind(module);
    boundGetX(); // 返回 81
    

    2、偏函数
    bind()的另一个简单用法就是使一个函数拥有预设的初始参数。这些参数会作为bind()的第二个参数跟在this后面,之后它们会插入到目标函数的参数列表的开始位置,传递给绑定函数的参数会跟在它们后面。

    function list() {
      return Array.prototype.slice.call(arguments);
    }
    
    var list1 = list(1, 2, 3); // [1, 2, 3]
    
    // Create a function with a preset leading argument
    var leadingThirtysevenList = list.bind(undefined, 37);
    
    var list2 = leadingThirtysevenList(); // [37]
    var list3 = leadingThirtysevenList(1, 2, 3); // [37, 1, 2, 3]
    

    3、配合setTimeout
    在默认情况下,使用window.setTimeout()时,this关键字会指向window(或全局)对象。当使用类的方法时,需要this引用类的实例,需要显式地把this绑定到回调函数以便继续使用实例。

    4、作为构造函数使用的绑定函数
    绑定函数适用于用new操作符去构造一个由目标函数创建的新的实例。当一个绑定函数是用来构建一个值的,原来提供的 this 就会被忽略。然而, 原先提供的那些参数仍然会被前置到构造函数调用的前面。

    function Point(x, y) {
      this.x = x;
      this.y = y;
    }
    
    Point.prototype.toString = function() { 
      return this.x + ',' + this.y; 
    };
    
    var p = new Point(1, 2);
    p.toString(); // '1,2'
    
    var emptyObj = {};
    var YAxisPoint = Point.bind(emptyObj, 0/*x*/);
    // 以下这行代码在 polyfill 不支持,
    // 在原生的bind方法运行没问题:
    //(译注:polyfill的bind方法如果加上把bind的第一个参数,即新绑定的this执行Object()来包装为对象,Object(null)则是{},那么也可以支持)
    var YAxisPoint = Point.bind(null, 0/*x*/);
    
    var axisPoint = new YAxisPoint(5);
    axisPoint.toString(); // '0,5'
    
    axisPoint instanceof Point; // true
    axisPoint instanceof YAxisPoint; // true
    new Point(17, 42) instanceof YAxisPoint; // true
    

    Polyfill

    bind()函数在 ECMA-262 第五版才被加入;它可能无法在所有浏览器上运行。你可以部份地在脚本开头加入以下代码,就能使它运作,让不支持的浏览器也能使用 bind() 功能。

    if (!Function.prototype.bind) {
      Function.prototype.bind = function(oThis) {
        if (typeof this !== 'function') {
          // closest thing possible to the ECMAScript 5
          // internal IsCallable 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() {
              // this instanceof fNOP === true时,说明返回的fBound被当做new的构造函数调用
              return fToBind.apply(this instanceof fNOP
                     ? this
                     : oThis,
                     // 获取调用时(fBound)的传参.bind 返回的函数入参往往是这么传递的
                     aArgs.concat(Array.prototype.slice.call(arguments)));
            };
    
        // 维护原型关系
        if (this.prototype) {
          // Function.prototype doesn't have a prototype property
          fNOP.prototype = this.prototype; 
        }
        // 下行的代码使fBound.prototype是fNOP的实例,因此
        // 返回的fBound若作为new的构造函数,new生成的新对象作为this传入fBound,新对象的__proto__就是fNOP的实例
        fBound.prototype = new fNOP();
    
        return fBound;
      };
    }
    
  • 相关阅读:
    css面试题目
    5. React-Router05 BrowserRouter 和hashrouter
    5. React-Router03 withRouter
    5. React-Router01
    CVE-2019-0708—微软RDP远程桌面代码执行漏洞复现
    正则表达式学习汇总
    CTF---PHP安全考题
    快速搭建主动诱导型开源蜜罐框架系统--hfish
    python--爬取网页存在某字符
    Linux 实用指令之查看端口开启情况
  • 原文地址:https://www.cnblogs.com/GeniusLyzh/p/9356887.html
Copyright © 2011-2022 走看看