js--手写call和apply方法干货注释满满-CSDN博客

43 阅读2分钟

我们都知道js中call和apply都是改变this指向的,这篇文章我们一起来实现call和apply的底层吧!我们先来看一下js中的call和apply的用法

一.用法

1.call用法 传递参数逗号分隔

// 1.js call的用法
function fnc(a,b,c) {
  console.log(this.name,a,b,c);
}
var obj = {
  name: "逍遥的码农",
};
// 这里我们想用fnc函数打印出obj对象里的name属性
// 把obj为参数给call函数传递过去
fnc.call(obj,"参数1","参数2","参数3")

2.apply用法 传递参数为数组

// 1.js apply的用法
function fnc(a,b,c) {
  console.log(this.name,a,b,c);
}
var obj = {
  name: "逍遥的码农",
};
// 这里我们想用fnc函数打印出obj对象里的name属性
// 把obj为参数给apply函数传递过去
fnc.apply(obj,["参数1","参数2","参数3"])

二.手写实现call

1.手写myCall改变this指向

function fnc(a, b, c) {
  console.log(this.name, a, b, c);
}
var obj = {
  name: "逍遥的码农",
};

Function.prototype.myCall = function (obj) {
  // 首先看一下这里的this 这里的this为fnc函数
  console.log(this);
  // 我们给传过来的obj添加fnc函数 相当于obj里面添加了一个p函数为fnc函数
  obj.p = this;
  // 运行p函数 这里fnc的this已经被改变为obj fnc函数正常打印出name
  obj.p();
  // 运行完成删除p方法 不能改变对象数据
  delete obj.p
};
fnc.myCall(obj);

这里this指向已经改变,但是还不可以传递参数接下来传参

2.传递参数 逗号分隔传参

function fnc(a, b, c) {
  console.log(this.name, a, b, c);
}
var obj = {
  name: "逍遥的码农",
};

Function.prototype.myCall = function (obj) {
  //这里用arguments 他是一个伪数组并不是真正的数组 需要给他转换成数组 这里使用Array.prototype.slice.call
  console.log(arguments)
  // 这里从第一个下标截取 因为第一个参数为obj 我们不需要
  var ars =  Array.prototype.slice.call(arguments,1)
  console.log(ars)
  // 首先看一下这里的this 这里的this为fnc函数
  console.log(this);
  // 我们给传过来的obj添加fnc函数 相当于obj里面添加了一个p函数为fnc函数
  obj.p = this;
  // 运行p函数 这里fnc的this已经被改变为obj fnc函数正常打印出name 给p传递参数
  obj.p(...ars);
  // 运行完成删除p方法 不能改变对象数据
  delete obj.p
};
fnc.myCall(obj,"参数1","参数2","参数3");

这里就完成了call方法 接下来的apply肯定小伙伴已经懂了吧 来咱们继续

二.手写实现apply

1.手写myApply 数组传递参数

Function.prototype.myApply = function (obj, arr) {
  // 这里的this还是为为fnc函数
  console.log(this);
  obj.p = this;
  // 这里的arr为数组直接传递过去就可以了
  obj.p(...arr);
  delete obj.p;
},
fnc.myApply(obj, ["参数1", "参数2", "参数3"]);

apply很简单 只要把call弄懂了apply就很简单啦