深入理解 JavaScript 中的 call 方法实现

什么是 call 方法

在 JavaScript 中,call() 是一个内置的函数方法,它允许你在特定的作用域中调用函数,即可以改变函数执行时的 this 指向。

基本语法:

javascript 复制代码
func.call(thisArg, arg1, arg2, ...)

原生 call 方法示例

javascript 复制代码
const person = {
    name:"ling_wu"
}

function getName(){
    console.log(this.name)
}

// 使用call改变this指向
getName.call(person); //输出:"ling_wu"

这个过程实际上的操作是person这个对象中创建了一个getName的函数,并且这个函数的this指向了person这个对象

javascript 复制代码
person = {
    name:"ling_wu",
    getName:function(){
        console.log(this.name);
    }
}

getName执行完成后再从person对象中删除getName这个属性

手动实现 call 方法

有了上面的初步分析我们来初步实现

第一步:基本实现

javascript 复制代码
Function.prototype.myCall = function(context){
    // getName.myCall(person)这个位置getName调用的myCall,所以this指向getName
    context.fn = this;
    const result = context.fn();
    delete context.fn;
    return result;
}

第二步:考虑参数

call是可以传递参数的,并且是都喊分隔,可以使用es6的...args来接收

javascript 复制代码
Function.prototype.myCall = function(context,...args){
    context.fn = this;
    const result = context.fn(...args);
    delete context.fn;
    return result;
}

第三步:对传入null做处理

call函数中如果传入的是null则默认指向全局对象(MDN中call函数是这样描述的),所以给context赋值一个默认值

javascript 复制代码
Function.prototype.myCall = function(context,...args){
    context = context || window;
    context.fn = this;
    const result = context.fn(...args);
    delete context.fn;
    return result;
}

第四步:对fn属性名做唯一处理,怕属性名冲突

javascript 复制代码
Function.prototype.myCall = function(context,...args){
    context = context || window;
    const fn = Symbol('fn')
    context[fn] = this;
    const result = context[fn](...args);
    delete context[fn];
    return result;
}

使用示例

javascript 复制代码
const person = {
    name:"ling_wu"
}

function getName(age,sex){
    console.log(`name:${this.name},age:${age},sex:${sex}`)
}

//使用原生的call
getName.call(person,26,'男'); //输出:name:ling_wu,age:26,sex:男

//使用我们自己实现的myCall
getName.myCall(person,26,'男'); //输出:name:ling_wu,age:26,sex:男

📢 关于作者

嗨!我是头发秃头小宝贝,一名热爱技术分享的开发者,专注于Vue / 前端工程化 / 实战技巧 等领域。

如果这篇文章对你有所帮助,别忘了 点赞 👍收藏 ⭐关注 👏,你的支持是我持续创作的最大动力!

相关推荐
不在逃避q30 分钟前
Trae/Vs Code/Cursor命令行无法跑npm命令
前端·arcgis·npm
夏殇之殁44 分钟前
包中创建自定义列表项。 . 使用自定义列表项进行数据绑定 . 将天气预报数据保存到本地内存表,通过LiveBindings进行显示。 ...
服务器·前端·javascript
The Chosen One9851 小时前
高进度算法模板速记(待完善)
java·前端·算法
陈随易1 小时前
MoonBit抓包模块pcap,查看电脑的每一次联网通信
前端·后端·程序员
新中地GIS开发老师2 小时前
WebGIS开发学生作品|低空航天管理与航线规划系统
前端·javascript·webgis·三维gis开发
用户059540174462 小时前
大模型对话记忆持久化踩坑实录:用 Playwright 自动化测了 300 次,终于揪出会话丢失的真凶
前端·css
丙氨酸長鏈2 小时前
Web前端入门第 问:JavaScript 一个简单的 IndexedDB 数据库入门示例
前端·javascript·数据库
kyriewen3 小时前
面试官让我手写虚拟列表——AI生成的版本,快速滚动几下就白屏了
前端·javascript·面试
IT_陈寒3 小时前
Vite热更新失效?你可能漏了这个配置
前端·人工智能·后端
梅孔立4 小时前
两种免费的翻译API调用方式详解 - Edge官方API与个人缓存服务
前端·缓存·edge