JavaScript面试:手写bind/call/apply函数

1.手写call和apply函数

手写call函数:

步骤:

1.判断第一个参数的类型

2.将当前的函数作为传入对象的方法

3.取出argument类数组的值

4.执行obj.当前函数(newarugument),并保存返回值

5.删除传入对象的方法

6.返回返回值

代码如下:

Function.prototype.newCall = function (obj) {
    if (typeof obj != "object" || obj == null) { obj = window }
    obj.fn = this
    let newArguments = [];
    for (let i = 1; i < arguments.length; i++) {
      newArguments.push(arguments[i])
    }
    var result = obj.fn(...newArguments)
    delete obj.fn
    return result
  }

手写apply函数:

apply函数和call函数唯一不同的就是参数不同,apply是有两个参数的。我们可以进行判断,如果没有第二个参数那么我们直接执行函数,如果有参数再去 做参数的处理。

代码如下:

  Function.prototype.newApply = function (obj, arr) {
    var result;
    if (typeof obj != "object" || obj == null) obj = window
    obj.fn = this
    if (arr == null) {
      result = obj.fn()
    } else {
      let newArgument = []
      for (let i = 0; i < arr.length; i++) {
        newArgument.push(arr[i])
      }
      result = obj.fn(...newArgument)
    }
    delete obj.fn;
    return result
  }

2.手写bind函数

首先我们需要清楚bind函数的作用以及一些特性。bind函数一般返回一个函数,并且具有以下的特性:

  1. 具有柯里化的特性
  2. 返回的函数可以进行new实例化(实例化后bind绑定的obj对象this会丢失)

我们来分析一下,事实上如果是单纯的改变this指向,bind 的内部并不复杂,因为它直接使用了apply函数。重要的是我们如何实现它的两个特性。

首先柯里化的特性我们是这样实现的:我们知道在内部我们会返回一个函数,因为我们就有了两个arguments,这两个arguments分别是我们先后传递的参数,我们只需要将这两个的arguments参数处理并且拼接就可以完成了。

接着就是new实例化的操作,首先我们如果使用了new操作,那么我们内部返回的函数的this就会指向这个构造函数的实例,如果不适用指向window,所以我们当其指向构造函数的实例时我们就将this绑定到apply上,如果不是就绑定在之前的obj上。最后再将我们调用函数的原型指向我们返回函数的原型上,这样一来我们相当于做了一个继承的操作,如果我们进行了实例化操作我们就可以拿到person原型上的数据了。

代码实现:

  Function.prototype.newBind = function (obj) {
    // 判断传入对象类型
    if (typeof obj != "object" || obj == null) obj = window
    var that = this
    // 外部函数参数
    var arr1 = Array.prototype.slice.call(arguments, 1);
    var newFun = function () {
      console.log(this)
      var arr2 = Array.prototype.slice.call(arguments);
      //判断时候进行类new实例化操作
      if (this instanceof newFun) {
        that.apply(this, arr1.concat(arr2))
      } else {
        that.apply(obj, arr1.concat(arr2))
      }
    }
    newFun.prototype = that.prototype
    return newFun;
  }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值