📕 重学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, 你好 小红

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

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

热门文章

最新文章

  • 1
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    23
  • 2
    Node.js 中实现多任务下载的并发控制策略
    32
  • 3
    【2025优雅草开源计划进行中01】-针对web前端开发初学者使用-优雅草科技官网-纯静态页面html+css+JavaScript可直接下载使用-开源-首页为优雅草吴银满工程师原创-优雅草卓伊凡发布
    25
  • 4
    【JavaScript】深入理解 let、var 和 const
    48
  • 5
    【04】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架二次开发准备工作-以及建立初步后端目录菜单列-优雅草卓伊凡商业项目实战
    44
  • 6
    【03】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架搭建-服务端-后台管理-整体搭建-优雅草卓伊凡商业项目实战
    53
  • 7
    【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
    55
  • 8
    如何通过pm2以cluster模式多进程部署next.js(包括docker下的部署)
    71
  • 9
    【01】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-需求改为思维导图-设计数据库-确定基础架构和设计-优雅草卓伊凡商业项目实战
    55
  • 10
    JavaWeb JavaScript ③ JS的流程控制和函数
    62