zoukankan      html  css  js  c++  java
  • 手动实现apply、call、bind

    手动实现apply、call、bind

    每个Function对象都存在apply()call()bind()方法,其作用都是可以在特定的作用域中调用函数,等于设置函数体内this对象的值,以扩充函数赖以运行的作用域。

    apply

    funct.apply(thisArg, [argsArray])
    thisArg: 必选,在funct函数运行时使用的this值,this可能不是该方法看到的实际值,如果这个函数处于非严格模式下,则指定为nullundefined时会自动替换为指向全局对象,原始值会被包装。
    argsArray: 可选,传递一个参数数组或者类数组对象,其中的数组元素将作为单独的参数传给funct函数,如果该参数的值为nullundefined,则表示不需要传入任何参数。
    实现思路,类似于Function.prototype.apply(),同样将_apply()方法挂载到Function.prototype,使得函数对象能够直接调用,在调用funct._apply()时,在_apply()方法中的this指向的是funct对象,将此funct对象作为一个变量赋予将要绑定的对象的一个属性中,使用将要绑定的对象来调用这个funct,即可实现this指针指向将要绑定的对象,对于参数的处理,直接使用ES6Spread运算符将数组展开作为参数传递。

    window.a = 1; // 定义一个全局变量
    var obj = {a: 2} // 定义一个对象用来绑定
    var funct = function(b, c) { console.log(this.a,b,c); return 1; }; // 定义一个函数用来执行
    
    funct(1, 2); // 1 1 2  // 直接执行,相当于window.funct(1, 2),this绑定于window
    funct.apply(obj, [1, 2]); // 2 1 2 // 使用apply将this绑定到obj对象
    
    Function.prototype._apply = function(base, args) { // 拓展Function原型
        base = base || window; // 传递绑定的对象为null或undefined时指向window
        base.fn = this; // 调用_apply时的this指向的是调用者也就是函数对象,将函数对象赋值给base对象的一个属性
        var result = base.fn(...args); // 调用base.fn时,fn中的this指针指向的是base,并使用Spread操作符展开参数传参
        delete base.fn; // 删除base对象的fn属性
        return result; // 将返回值返回
    }
    
    funct._apply(obj, [1, 2]); // 2 1 2 // this绑定到了obj对象
    

    call

    funct.call(thisArg[, arg1[, arg2[, ...]]])
    thisArg: 必选,在funct函数运行时使用的this值,this可能不是该方法看到的实际值,如果这个函数处于非严格模式下,则指定为nullundefined时会自动替换为指向全局对象,原始值会被包装。
    arg1, arg2, ...: 可选,指定的参数列表。
    实现思路,类似于Function.prototype.call(),同样将_call()方法挂载到Function.prototype,使得函数对象能够直接调用,在调用funct._call()时,在_call()方法中的this指向的是funct对象,将此funct对象作为一个变量赋予将要绑定的对象的一个属性中,使用将要绑定的对象来调用这个funct,即可实现this指针指向将要绑定的对象,对于参数的处理,使用ES6Rest操作符来接收剩余参数,使用ES6Spread运算符将数组展开作为参数传递。

    window.a = 1; // 定义一个全局变量
    var obj = {a: 2} // 定义一个对象用来绑定
    var funct = function(b, c) { console.log(this.a,b,c); return 1; }; // 定义一个函数用来执行
    
    funct(1, 2); // 1 1 2  // 直接执行,相当于window.funct(1, 2),this绑定于window
    funct.call(obj, 1, 2); // 2 1 2 // 使用call将this绑定到obj对象
    
    Function.prototype._call = function(base, ...args) { // 拓展Function原型,使用Rest操作符接收剩余参数
        base = base || window; // 传递绑定的对象为null或undefined时指向window
        base.fn = this; // 调用_call时的this指向的是调用者也就是函数对象,将函数对象赋值给base对象的一个属性
        var result = base.fn(...args); // 调用base.fn时,fn中的this指针指向的是base,并使用Spread操作符展开参数传参
        delete base.fn; // 删除base对象的fn属性
        return result; // 将返回值返回
    }
    
    funct._call(obj, 1, 2); // 2 1 2 // this绑定到了obj对象
    

    bind

    funct.bind(thisArg[, arg1[, arg2[, ...]]])
    thisArg: 必选,调用绑定函数时作为this参数传递给目标函数的值,如果使用new运算符构造绑定函数,则忽略该值,当作为回调提供时,作为thisArg传递的任何原始值都将转换为object,如果bind函数的参数列表为空,或者thisArgnullundefined,执行作用域的this将被视为新函数的thisArg
    arg1, arg2, ...: 可选,当目标函数被调用时,被预置入绑定函数的参数列表中的参数。
    实现思路,类似于Function.prototype.bind(),同样将_bind()方法挂载到Function.prototype,使得函数对象能够直接调用,利用箭头函数在词法上绑定this值的特性,返回一个指定了this的函数,倘若不使用箭头函数,也可以将this值分配给封闭的变量来构建闭包,然后是类似于apply方法的实现,来绑定this到指定的对象。

    window.a = 1; // 定义一个全局变量
    var obj = {a: 2} // 定义一个对象用来绑定
    var funct = function(b, c) { console.log(this.a,b,c); return 1; }; // 定义一个函数用来执行
    
    funct(1, 2); // 1 1 2  // 直接执行,相当于window.funct(1, 2),this绑定于window
    var bindFunct = funct.bind(obj, 1, 2); // 使用bind将this绑定到obj对象,bind方法返回一个原函数的拷贝,并拥有指定的this值和初始参数。
    bindFunct(); // 2 1 2 
    
    Function.prototype._bind = function(base, ...args1) { // 拓展Function原型,使用Rest操作符接收剩余参数
        return (...args2) => { // 箭头函数不会生成自身作用域下的this,会从自己的作用域链的上一层继承this
            base = base || window; // 传递绑定的对象为null或undefined时指向window
            base.fn = this; // 调用箭头函数时的this指向的是调用者也就是函数对象,将函数对象赋值给base对象的一个属性
            var result = base.fn(...args1, ...args2); // 调用base.fn时,fn中的this指针指向的是base,并使用Spread操作符展开参数传参
            delete base.fn; // 删除base对象的fn属性
            return result; // 将返回值返回
        }
    }
    
    var _bindFunct = funct._bind(obj, 1, 2); // 绑定对象
    _bindFunct(); // 2 1 2 
    

    每日一题

    https://github.com/WindrunnerMax/EveryDay
    

    参考

    https://www.jianshu.com/p/57a876fe66c8
    
  • 相关阅读:
    CodeForces 347B Fixed Points (水题)
    CodeForces 347A Difference Row (水题)
    CodeForces 346A Alice and Bob (数学最大公约数)
    CodeForces 474C Captain Marmot (数学,旋转,暴力)
    CodeForces 474B Worms (水题,二分)
    CodeForces 474A Keyboard (水题)
    压力测试学习(一)
    算法学习(一)五个常用算法概念了解
    C#语言规范
    异常System.Threading.Thread.AbortInternal
  • 原文地址:https://www.cnblogs.com/WindrunnerMax/p/12814218.html
Copyright © 2011-2022 走看看