📕 重学JavaScript:如何实现一个`call`/`apply`?

简介: 这次要说的 call/apply 方法其实和 bind 极其类似。

📕 重学JavaScript:如何实现一个call/apply

嗨,大家好!这里是道长王jj~ 🎩🧙‍♂️

这次要说的 call/apply 方法其实和 bind 极其类似。

它们可以让你改变一个函数的 this 指向,也就是让这个函数执行时,里面的 this 指向你想要的对象。😮

❓ 什么是call/apply

比如,你有一个函数叫 fn ,它会打印出 this 的 z 属性和两个参数 x 和 y 的和,就像这样:

function fn(x, y) {
   
  console.log(this.z);
  console.log(x + y);
}

然后,你有一个对象叫 obj ,它有一个 z 属性,就像这样:

var obj = {
   
  z: 1
};

现在,你想让 fn 的 this 指向 obj ,而且给 fn 传递两个参数 2 和 3 ,就可以使用 call/apply方法了!😊

你只要这样写:

fn.call(obj, 2, 3); // call 方法是一个一个传入参数
fn.apply(obj, [2, 3]); // apply 方法是通过一个数组传入参数

就会打印出:

1
5

他们俩区别就是传递参数的方式不同。call 方法是一个一个传入参数,而 apply 方法是通过一个数组传入参数。😁

那么,现在我们要自己实现call/apply,该怎么办呢?🤔

🔰 思路分析

其实核心套路其实和bind差不多,都是就两件事情。

  1. 让一个普通函数的 this 指向你想要的对象。
  2. 让一个构造函数的原型对象上的属性不会丢失。

确定好思路之后,我们就可以进行伪代码环节了。

💫 伪代码思路

1. 把第一个参数作为新的 this ,把剩下的参数作为新函数的初始参数,放在一个数组里。
2. 需要注意 call 方法是一个一个传入参数,而 apply 方法是通过一个数组传入参数。
3. 用 eval 函数执行原来的函数,把新的 this 和参数传进去。
4. 返回执行结果

⭕ 代码实现

function myCall(obj) {
   
  // 如果 obj 参数为空,则默认为 window 对象
  obj = obj || window;
  // 使用 Symbol 函数创建一个唯一的标识符
  const fnSymbol = Symbol();
  // 把原来的函数赋值给 obj 的 fnSymbol 属性
  obj[fnSymbol] = this;
  // 获取剩余参数
  const args = [...arguments].slice(1);
  // 构造字符串代码
  let code = `obj[fnSymbol](${
     args})`;
  // 执行代码并返回结果
  let result = eval(code);
  // 删除 obj 的 fnSymbol 属性
  delete obj[fnSymbol];
  // 返回结果
  return result;
};


function myApply(obj) {
   
  // 如果 obj 参数为空,则默认为 window 对象
  obj = obj || window;
  // 使用 Symbol 函数创建一个唯一的标识符
  const fnSymbol = Symbol();
  // 把原来的函数赋值给 obj 的 fnSymbol 属性
  obj[fnSymbol] = this;
  // 获取剩余参数(数组)
  const args = arguments[1];
  // 构造字符串代码
  let code = `obj[fnSymbol](${
     args})`;
  // 执行代码并返回结果
  let result = eval(code);
  // 删除 obj 的 fnSymbol 属性
  delete obj[fnSymbol];
  // 返回结果
  return result;
};

💥 测试一下看看有没有问题

function sayHello(name) {
   
  return "Hello, " + this.greeting + " " + name;
}

sayHello.myCall = myCall;
sayHello.myApply = myApply;

var obj = {
    greeting: "你好" };

// 用 myCall 调用函数
var result1 = sayHello.myCall(obj, "小明");

// 用 myApply 调用函数
var result2 = sayHello.myApply(obj, ["小红"]);

console.log(result1); // Hello, 你好 小明
console.log(result2); // Hello, 你好 小红

🎉 你觉得怎么样?这篇文章可以给你带来帮助吗?如果你有任何疑问或者想进一步讨论相关话题,请随时发表评论分享您的想法,让其他人从中受益。🚀✨

目录
相关文章
|
11月前
|
JavaScript 前端开发
js中的bind,call,apply方法的区别以及用法
JavaScript中,`bind`、`call`和`apply`均可改变函数的`this`指向并传递参数。其中,`bind`返回一个新函数,不立即执行;`call`和`apply`则立即执行,且`apply`的参数以数组形式传递。三者在改变`this`指向及传参上功能相似,但在执行时机和参数传递方式上有所区别。
180 1
|
12月前
|
JavaScript 前端开发
JS高级—call(),apply(),bind()
【10月更文挑战第17天】call()`、`apply()`和`bind()`是 JavaScript 中非常重要的工具,它们为我们提供了灵活控制函数执行和`this`指向的能力。通过合理运用这些方法,可以实现更复杂的编程逻辑和功能,提升代码的质量和可维护性。你在实际开发中可以根据具体需求,选择合适的方法来满足业务需求,并不断探索它们的更多应用场景。
105 1
|
JavaScript 前端开发
js 中call()和apply()
js 中call()和apply()
77 1
|
自然语言处理 JavaScript 前端开发
JS中this的应用场景,再了解下apply、call和bind!
该文章深入探讨了JavaScript中`this`关键字的多种应用场景,并详细解释了`apply`、`call`和`bind`这三个函数方法的使用技巧和差异。
|
JavaScript 前端开发
this指向的几种情况以及js简单实现call、apply、bind___六卿
本文讨论了JavaScript中`this`的指向规则,并提供了`call`、`apply`和`bind`方法的简单实现,用于改变函数的`this`指向。
69 0
this指向的几种情况以及js简单实现call、apply、bind___六卿
|
JavaScript
js的this与call,apply,bind
js的this与call,apply,bind
|
JavaScript 前端开发
js 中call()和apply()
js 中call()和apply()
83 0
|
JavaScript 前端开发
javascript中的call和apply
javascript中的call和apply
|
JavaScript 前端开发
JavaScript中call()与apply()的作用与区别?
JavaScript中call()与apply()的作用与区别?
|
前端开发 JavaScript 开发者
揭秘JavaScript魔法三剑客:call、apply、bind,解锁函数新世界,你的前端之路因它们而精彩!
【8月更文挑战第23天】在 JavaScript 的世界里,`call`、`apply` 和 `bind` 这三个方法常常让新手感到困惑。它们都能改变函数执行时的上下文(即 `this` 的指向),但各有特点:`call` 接受一系列参数并直接调用函数;`apply` 则接收一个参数数组,在处理不确定数量的参数时特别有用;而 `bind` 不会立即执行函数,而是创建一个新版本的函数,其 `this` 上下文已被永久绑定。理解这三个方法能帮助开发者更好地运用函数式编程技巧,提升代码灵活性和可维护性。
134 0

热门文章

最新文章