JavaScript手写call,apply,bind方法

 更新时间:2022年06月24日 08:21:19   作者:​ 前端若水   ​  
这篇文章主要介绍了JavaScript手写call,apply,bind方法,call,bind,apply方法都是JavaScript原生的方法,挂载在Function原型上,使得所有函数都可以调用

前言

改变this指向在书写业务的时候经常遇到,我们经常采用以下方法进行改写

  • 使用作用声明变量存储this
  • 使用jJavaScript的原生方法call,apply,以及bind进行改写

第一种方法就不说了,就是一个变量存储的问题,主要说第二种如何实现的

call,bind,apply方法都是JavaScript原生的方法,挂载在Function原型上,使得所有函数都可以调用,今天我们来实现一下call,apply,bind吧

改写this实现思路

我们声明一个函数,函数接受俩个参数,第一个参数是接受改变的this指向,第二个是剩余参数,用于执行改变方法后传递的使用参数,在函数中里面声明一个变量用于存储传递过来的this,遵循this指向的准则,this是在执行的时候生成的,函数的准则是谁调用它就指向谁,传递过来的this是一个对象,然后在传递过来的this上面声明一个方法,声明的方法就是当前函数,该方法由传递过来的this进行调用执行,这样就改变了this指向问题,在把传递过来的参数除第一个外全部传递给声明的方法,我们来实现一下

前期准备

这些数据用于配合手写的方法,由于call,bind,apply他们都是需要把他们挂载到函数原型上,函数才能调用的到,我们这里也把他挂载到原型上

 var name = '前端';
        var age = "7";
        let obj = {
            name: '若水',
            age: '20'
        };

 function fnLog(arg) {
     let str = `我叫${this.name}今年${this.age}岁了`;
  console.log(str, '传递过来的', arg);
}

手写的call,bind,apply方法第一个参数都是改变的this指向,第二个参数是传递的参数

手写call方法

call方法是改变this后立即执行

  Function.prototype.myCall = function(content, ...arg) {
            // 创建一个变量接受改变的this,如果改变的this为空则采用window为默认this
            let newThis = content || window;
            /**newThis是一个对象,它是传递过来的this,在newThis上新增一个方法,这个方法就是
            当前函数 ,this就是指向的myCall,调用这个方法就可以改变this指向,因为函数是谁调用
            它this就指向谁 
            **/
            newThis.fn = this;
           /**执行改变this方法,接受返回值,这里容易被误导,这里是把myCall传递过来的参数传递
            给了改变this的函数,由于不确定传递多少使用了剩余参数,这里也是 **/
            let result = newThis.fn(...arg);
            //删除传递过来this上声明的方法,防止出现问题
            delete newThis.fn;
            // 将执行结果返回
            return result;
        };
        //执行手写的call方法
        fnLog.myCall(obj, 'myCall');

手写apply方法

apply传递的参数只能传递数组

//如果arg没有传递参数,默认为空数组
      Function.prototype.myApply = function(content, arg = []) {
            // 判断传递参数是否为数组,如果不为数组则抛出错误,为数组则继续执行
            if (!Array.isArray(arg)) {
                throw '传递参数必须为数组';
            }
            // 创建一个变量接受改变的this,如果改变的this为空则采用window为默认this
            let newThis = content || window;
            // 给当前传递过来的this,添加一个方法,遵循this准则,谁调用就指向谁的原则
            newThis.fn = this;
            // 同mycall相同
            let result = newThis.fn(arg);
           //删除传递过来this上声明的方法,防止出现问题
            delete newThis.fn;
            // 将执行结果返回
            return result;
        };
        //执行
        fnLog.myApply(obj, [1, 212, 232]);

手写bind方法

bind不是立即执行而是返回一个新的函数

  Function.prototype.myBind = function(content, ...arg) {
            // 创建一个变量接受改变的this,如果改变的this为空则采用window为默认this
            let newThis = content || window;
        // 给当前传递过来的this,添加一个方法,遵循this准则,谁调用就指向谁的原则
            newThis.fn = this;
 // 由于bind不是立即执行,是返回一个函数作为bind方法执行的返回值,所以这里需要return出去一个函数
            return function() {
   // 然后在把执行当前的方法进行执行并把myBind接受剩余参数传递过去,接受返回值
                let result = newThis.fn(...arg);
                //删除当前的函数以及传递过来的this,防止出现问题
                delete newThis.fn;
                // 将执行结果返回
                return result;
            }
        };
       //调用bind函数,获取返回值,他的返回值是一个函数,所以我们需要在调用一下
        let f1 = fnLog.myBind(obj, 2);
        //调用bind的返回值
        f1()

到此这篇关于JavaScript手写call,apply,bind方法的文章就介绍到这了,更多相关JavaScript call内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • javascript设计模式 – 建造者模式原理与应用实例分析

    javascript设计模式 – 建造者模式原理与应用实例分析

    这篇文章主要介绍了javascript设计模式 – 建造者模式,结合实例形式分析了javascript建造者模式相关概念、原理、应用场景及操作注意事项,需要的朋友可以参考下
    2020-04-04
  • JavaScript面向对象分层思维全面解析

    JavaScript面向对象分层思维全面解析

    这篇文章主要介绍了JavaScript面向对象分层思维,js本身不是面向对象语言,在我们实际开发中其实很少用到面向对象思想。下文关于js面向对象知识给大家介绍的非常详细,感兴趣的朋友一起看看吧
    2016-11-11
  • 如何在微信小程序中实现Mixins方案

    如何在微信小程序中实现Mixins方案

    这篇文章主要给大家介绍了关于如何在微信小程序中实现Mixins方案的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用微信小程序具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-06-06
  • Node调试工具JSHint的安装及配置教程

    Node调试工具JSHint的安装及配置教程

    Node的优势我就不再乱吹捧了,它让javascript统一web的前后台成为了可能。但是对于新手来说,server端的JS代码可能不像client端的代码那么好调试,直观。client端JS代码的调试基本上经历了一个从“肉眼--alert()--firebug(或者其它的developer tools)”的一个过程。而对于server端的调试,可能新手仍然停留在使用“肉眼--console()”的阶段。其实,Node经过了这么多年(虽然才短短几年)的发展,也有了很多不错的第三方的调试工具。包括Node内建的调试工具debugger、node-inspector等。
    2014-05-05
  • js 操作select与option(示例讲解)

    js 操作select与option(示例讲解)

    本篇文章主要是对js 操作select与option的示例进行了介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2013-12-12
  • ES6 中可以提升幸福度的小功能

    ES6 中可以提升幸福度的小功能

    这篇文章主要介绍了ES6 中可以提升幸福度的小功能,在量解构赋值的用途,函数的用处等方面给大家介绍,需要的朋友可以参考下
    2018-08-08
  • js实现签到日历

    js实现签到日历

    这篇文章主要为大家详细介绍了js实现签到日历,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • 微信小程序前端通过weixin://wxpay/bizpayurl生成支付二维码全过程

    微信小程序前端通过weixin://wxpay/bizpayurl生成支付二维码全过程

    这篇文章主要给大家介绍了关于微信小程序前端通过weixin://wxpay/bizpayurl生成支付二维码的相关资料,weixin://wxpay/bizpayurl 是一个微信支付的链接地址,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-07-07
  • JavaScript中变量提升机制示例详解

    JavaScript中变量提升机制示例详解

    这篇文章主要给大家介绍了关于JavaScript中变量提升机制的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用JavaScript具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-12-12
  • 详解如何在webpack中做预渲染降低首屏空白时间

    详解如何在webpack中做预渲染降低首屏空白时间

    这篇文章主要介绍了详解如何在webpack中做预渲染降低首屏空白时间,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08

最新评论