手写 call、apply 及 bind 函数

手写 call、apply 及 bind 函数

一、介绍

1)call apply bind 功能:重定义 this 对象
bind 返回的是一个新函数,必须调用才会执行
2)参数

var obj = {   
  name: 'zs',
  objAge: this`在这里插入代码片`.age,
  myFunc: function (fm, t) {
    console.log(this.name + '年龄:' + this.age + ' 来自 ' + fm + ' 去往 ' + t);
  }
}
var db ={
  name: 'dd',
  age: 34
}

a. 第一个参数都是 this 指向的对象
b. 第二个参数
call 的参数是直接放入,以逗号分隔,后面的 n 个参数也是直接放到后面

obj.myFunc.call(db, 'a', 'b');    // dd年龄:34 来自 a 去往 b

apply 的参数必须放在一个数组里传进去

obj.myFunc.apply(db, ['c', 'd'])  // dd年龄:34 来自 c 去往 d

bind 的参数和 call 是一样的

obj.myFunc.bind(db,['e','f'])();  // dd年龄:34 来自 e,f 去往 undefined
obj.myFunc.bind(db,'e','f')();    // dd年龄:34 来自 e 去往 f

二、实现

  1. call 函数的实现
/**
 * 实现步骤
 * 1. 判断调用对象是否为函数
 * 2. 判断传入上下文对象是否存在,不存在则设置为 window
 * 3. 处理传入的参数,截取第一个参数后的所有参数
 * 4. 将函数作为上下文对象的一个属性
 * 5. 使用上下文对象来调用这个方法,并保存返回结果
 * 6. 删除刚才新增的属性
 * 7. 返回结果
 */
Function.prototype.myCall = function (context) {
  // 1. 判断调用对象是否为函数
  if (typeof this !== 'function') {
    console.error('type error');
  }
  // 2. 判断传入上下文对象是否存在,不存在则设置为 window
  context = context || globalThis;
  // 3. 截取第一个参数后的所有参数
  let args = [...arguments].slice(1);
  // 4. 将调用函数设为对象的属性
  context.fn = this;
  // 5. 使用上下文对象来调用这个方法,并保存返回结果
  let result = context.fn(...args);
  // 6. 删除刚才新增的属性
  delete context.fn;
  // 7. 返回结果
  return result;
}
  1. apply 函数的实现
/**
 * 1. 判断当前操作对象是否为函数
 * 2. 判断上下文对象是否存在,不存在则设为 window
 * 3. 处理传入的参数,获取第二个参数
 * 4. 将调用函数设为上下文对象的属性
 * 5. 使用上下文对象执行这个方法,并保存结果
 * 6. 删除新增的属性
 * 7. 返回结果
 */
Function.prototype.myApply = function(context) {
  // 1. 判断当前操作对象是否为函数
  if(typeof this !== 'function') {
    console.error('type error');
  }
  // 2. 判断上下文对象是否存在,不存在则设为 window
  context = context || globalThis; // node 设为 globalThis
  
  // 3. 处理传入的参数,获取第二个参数
  let args = arguments[1] || [];
  
  // 4. 将调用函数设为上下文对象的属性
  context.fn = this;

  // 5. 使用上下文对象执行这个方法,并保存结果
  let result = context.fn(...args);
 
  // 6. 删除新增的属性
  delete context.fn;
  // 7. 返回结果
  return result;
}
  1. bind 函数的实现
Function.prototype.myBind = function(context) {
  // 1. 判断调用对象是否为函数
  if(typeof this !== 'function') {
    console.error('type error');
  }

  // 2. 获取参数
  let args = [...arguments].slice(1);
  let fn = this;

  return function Fn() {
    // 3. 根据调用方式,传入不同的绑定值
    return fn.apply(
      this instanceof Fn ? this : context,
      args.concat(...arguments)
    );
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值