专栏首页code秘密花园手动实现call apply bind

手动实现call apply bind

基本使用

都是用来改变一个函数的this指向,用法略有不同。

call:后面的参数为调用函数的参数列表

function greet(name) {
  console.log(this.animal,name);
}

var obj = {
  animal: 'cats'
};

greet.call(obj,'猫咪');

apply:第二个参数为调用函数的参数数组

function greet(name) {
  console.log(this.animal,name);
}

var obj = {
  animal: 'cats'
};

greet.apply(obj,['猫咪']);

bind:当绑定函数被调用时,bind传入的参数会被插入到目标函数的参数列表的开始位置,传递给绑定函数的参数会跟在它们后面。

var fun = function (name1,name2){
    console.log(this);
    console.log(name);
}.bind({a:1},"name1");
    fun("name2");

手动实现

  1. context 为可选参数,如果不传的话默认上下文为 window;
  2. context 创建一个 Symbol 属性,调用后即删除,不会影响context
Function.prototype.myCall = function (context) {
      if (typeof this !== 'function') {
        return undefined; // 用于防止 Function.prototype.myCall() 直接调用
      }
      context = context || window;
      const fn = Symbol();
      context[fn] = this;
      const args = [...arguments].slice(1);
      const result = context[fn](...args);
      delete context[fn];
      return result;
    }

apply实现类似call,参数为数组

Function.prototype.myApply = function (context) {
      if (typeof this !== 'function') {
        return undefined; // 用于防止 Function.prototype.myCall() 直接调用
      }
      context = context || window;
      const fn = Symbol();
      context[fn] = this;
      let result;
      if (arguments[1] instanceof Array) {
        result = context[fn](...arguments[1]);
      } else {
        result = context[fn]();
      }
      delete context[fn];
      return result;
    }

1.判断是否为构造函数调用

2.注意参数要插入到目标函数的开始位置

Function.prototype.myBind = function (context) {
      if (typeof this !== 'function') {
        throw new TypeError('Error')
      }
      const _this = this
      const args = [...arguments].slice(1)
      return function F() {
        // 判断是否用于构造函数
        if (this instanceof F) {
          return new _this(...args, ...arguments)
        }
        return _this.apply(context, args.concat(...arguments))
      }
    }

本文分享自微信公众号 - code秘密花园(code_mmhy),作者:ConardLi

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-02-18

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • HTTP/3干货总结

    Google(pbuh) 公司拥有最流行的 web 浏览器(Chrome)和两个最流行的网站(#1 Google.com #2 Youtube.com)...

    ConardLi
  • Node进阶——之事无巨细手写Koa源码

    对比发现,相对原生,Koa多了两个实例上的use、listen方法,和use回调中的ctx、next两个参数。这四个不同,几乎就是Koa的全部了,也是这四个不同...

    ConardLi
  • 原型和原型链

    function Foo(){} 相当于 var Foo = new Function(){}

    ConardLi
  • 手写apply、call、bind

    各位宝宝,马上就要过中国年了,已经开启了放假模式了吗?放假了就好好的休息哈,该玩的时候玩、该学的时候学,就对了~

    用户3258338
  • 聊聊ribbon的retry

    spring-cloud-netflix-ribbon-2.0.0.RELEASE-sources.jar!/org/springframework/cloud...

    codecraft
  • SpringMVC 解毒1

    学Java开发的同学始终避不开Spring,学JavaWeb开发的同学就更避不开SpringMVC了。凡是有点追求的程序员肯定也想读一读Spring和Sprin...

    zhangheng
  • asp.net web api 异常捕获

    1 向客户端发送错误消息 使用throw new HttpResponseException()向客户端抛出错误信息。 HttpResponseExceptio...

    甜橙很酸
  • Canvas系列(7):形变

    CSS3中有一个很重要的点,就是形变。他分为移动,缩放、旋转和倾斜。在Canvas中,形变都是基于坐标做的,所以,并没有直接的API支持倾斜,其它几种都是有独立...

    kai666666
  • SpringApplication到底run了什么(下)

    在上篇文章中SpringApplication到底run了什么(上)中,我们分析了下面这个run方法的前半部分,本篇文章继续开工

    Java学习录
  • 高通是小米股东,为什么855首发不是小米? | 拔刺

    镁客网

扫码关注云+社区

领取腾讯云代金券