前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >bind、call、apply的实现

bind、call、apply的实现

作者头像
kai666666
发布2020-10-17 10:06:38
4160
发布2020-10-17 10:06:38
举报
文章被收录于专栏:橙光笔记橙光笔记

bindcallapply是JavaScript中Function.prototype非常重要的三个方法,他们的作用是改变this的指向。三者的区别是:

bind返回一个函数,该函数改变了this的指向。 call直接调用函数,也可以传递参数用逗号隔开。 apply直接调用函数,也可以传递参数使用数组传递给第二个参数。

我们现在详细解读一下各个函数的实现方式。

bind的实现

bind的基本用法:

  1. 函数调用bind,返回一个新的函数。
  2. bind方法的第一个参数是宿主对象,也就是执行的this
  3. bind返回函数执行时候的参数是bind方法第二个至多个参数与调用时参数的合集。

bind简单实现:

代码语言:javascript
复制
Function.prototype.bind = function (context) {
    var self = this;// 这个this其实是真正的函数
    // 获取第二至多个参数
    var args = Array.prototype.slice.call(arguments, 1);
    // 返回一个函数 该函数是真正执行时的函数
    return function () {
        // 获取真正执行时传进来的函数
        var bindArgs = Array.prototype.slice.call(arguments);
        // 合并参数 并且调用函数
        return self.apply(context, args.concat(bindArgs));
    }
}

这个简单的bind已经解决了上面的三个基本用法了,其实bind还有2个附加的特性:

  1. 如果上面self不是函数(防止非函数的原型指向Function.prototype),那么会报错。
  2. 从改变this的指向来看,new的优先级大于bind

功能更强大的bind实现:

代码语言:javascript
复制
Function.prototype.bind = function (context) {

    var self = this;
    if (typeof self !== "function") {// 如果self不是函数则报错
      throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
    }

    var args = Array.prototype.slice.call(arguments, 1);

    // 定义一个中间函数 让返回的函数继承它
    var FN = function () {};

    var returnFn = function () {
        var bindArgs = Array.prototype.slice.call(arguments);
        // 重点 如果返回函数的this是FN 说明是new出来的 this就是new的对象 否则是context
        return self.apply(this instanceof FN ? this : context, args.concat(bindArgs));
    }

    // FN的原型指向函数的原型
    FN.prototype = self.prototype;
    // 返回的函数继承FN
    returnFn.prototype = new FN();
    return returnFn;
}

call的实现

call的基本用法:

  1. 函数调用call,函数会执行,并且this指向了第一个函数。
  2. call方法的第一个参数是null或者undefined的时候this会绑定在全局对象上。
  3. call方法第二个至多个参数会传给执行的方法。

call方法简单实现:

代码语言:javascript
复制
Function.prototype.call = function (context) {
    // 如果为空 则绑定在全局函数
    var context = context || window;
    // 使用context.fn() 来调用函数 来模拟fn绑定在context上
    context.fn = this;

    var args = [];
    for(var i = 1, len = arguments.length; i < len; i++) {
        args.push('arguments[' + i + ']');
    }

    // 这里比较尴尬 因为context.fn调用的时候 无法把不定长的arguments 一个一个地传进去
    // 所以就使用eval方法了 当然可以用apply但是稍后我们也要实现它 所以就不能用了
    var result = eval('context.fn(' + args +')');

    // 删除添加的方法(毁尸灭迹)
    delete context.fn;
    return result;
}

apply的实现

apply的基本用法:

  1. 函数调用apply,函数会执行,并且this指向了第一个函数。
  2. apply方法的第一个参数是null或者undefined的时候this会绑定在全局对象上。
  3. apply方法第二个参数是一个数组,相当于函数执行时的参数。

apply方法简单实现:

代码语言:javascript
复制
Function.prototype.apply = function (context, arr) {
    var context = context || window;
    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;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-04-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • bind的实现
  • call的实现
  • apply的实现
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档