首页 > 技术文章 > 理解并手写 apply() 函数

HuiTaiLang1216 2022-03-08 09:04 原文

apply()函数,在功能上类似于call(),只是传递参数的格式有所不同。

dog.eat.call(cat, '鱼', '肉');   
dog.eat.apply(cat, ['鱼', '肉']);

因此我们完全可以套用 '上一篇对call()的分析,得到下列代码。

Function.prototype.myApply = function(obj){
  // 判断调用对象是否为函数
  if(typeof this !== 'function'){
    console.error('type error!')
  }
  // 判断绑定的对象
  obj = obj || window;
  obj.fn = this;
  // 将执行结果保存并返回
  let result = obj.fn();
  // 删除context.fn属性
  delete obj.fn;
  return result;
}

最后考虑下方法中使用的参数(是传递过来的第二个参数),并且格式就是数组,可以之间使用。

Function.prototype.myApply = function(obj){
  if(typeof this !== 'function'){
    console.error('type error!')
  }
  obj = obj || window;
  obj.fn = this;
  // 之间使用传递过来的数组
  let result = obj.fn(...arguments[1]);
  delete obj.fn;
  return result;
}

当没有数组传递过来的时候,arguments[1]获取不到,会报错,因此要再加一层判断。

Function.prototype.myApply = function(obj){
  if(typeof this !== 'function'){
    console.error('type error!')
  }
  obj = obj || window;
  obj.fn = this;
  // 判断arguments[1]是否存在
  if(arguments[1]){
    result = obj.fn(...arguments[1]);
  }else{
    result = obj.fn();
  }
  delete obj.fn;
  return result;
}

最后通过一个例子,来验证是否达到apply()的功能要求。

Function.prototype.myApply = function(obj){
  if(typeof this !== 'function'){
    console.error('type error!')
  }
  obj = obj || window;
  obj.fn = this;
  // 判断arguments[1]是否存在
  if(arguments[1]){
    result = obj.fn(...arguments[1]);
  }else{
    result = obj.fn();
  }
  delete obj.fn;
  return result;
}
let dog = {   
  name: '狗',   
  eat(food1, food2) {     
    console.log(this.name + '爱吃' + food1 + food2);   
  } 
} 
let cat = {   
  name: '猫', 
} 
dog.eat.apply(cat, ['鱼', '肉']); // 猫爱吃鱼肉 
dog.eat.myApply(cat, ['鱼', '肉']); // 猫爱吃鱼肉

 另外两篇:'对apply()函数的分析' 和 '对bind()函数的分析' 。

推荐阅读