5.實現 call

call 是 JavaScript 中非常核心的函數方法之一。它能改變函數的執行上下文(也就是 this 的指向),在日常開發和面試中都極其常見。本文將帶你一步步實現一個 Function.prototype.call 的自定義版本,真正理解它的底層原理。


? 一、call 方法做了什么?

在 MDN 中,Function.prototype.call() 是這樣定義的:

call() 方法使用一個指定的 this 值和若干個指定的參數(參數的列表)來調用一個函數。

通俗來講,它的作用就是:

  • 顯式指定函數的 this 指向;

  • 并立即執行該函數;

  • 參數可以依次傳入。


📌 二、原生 call 的底層邏輯拆解

來看一段模擬的執行邏輯:

var obj = {x: 100,fn() {console.log(this.x);}
};
obj.fn(); // 輸出 100

上面 fn() 的 this 指向 obj,因為是以 obj.fn() 的形式調用。

call 就是模擬了類似的過程——把函數掛載到目標對象上執行,從而實現 this 指向綁定。


🧠 三、call 方法內部做了哪些事?

  1. 判斷傳入的 context(目標對象)是否為值類型(如字符串、數字),如果是,就轉為對象(如 'abc'new String('abc'));

  2. 將函數臨時設為 context 的屬性;

  3. 通過 context.fn() 執行函數,此時 this 指向 context;

  4. 刪除臨時掛載的函數屬性,防止污染;

  5. 返回函數的執行結果。


🔧 四、手動實現 call 方法(完整版)

Function.prototype.myCall = function (context = window, ...args) {if (typeof context !== 'object' && typeof context !== 'function') {context = new Object(context); // 將值類型轉換為對象}const fnKey = Symbol();       // 創建唯一屬性名,避免覆蓋已有屬性context[fnKey] = this;        // this 是當前函數,即被調用的函數const result = context[fnKey](...args); // 執行函數,綁定 this 并傳參delete context[fnKey];        // 清理屬性,防止污染return result;                // 返回函數執行結果
};

🧪 五、測試用例驗證

function f(a, b) {console.log(a + b);       // 輸出 3console.log(this.name);   // 輸出 1
}const obj = { name: 1 };
f.myCall(obj, 1, 2);        // 等價于 f.call(obj, 1, 2)

輸出結果:

3
1

💬 六、值類型綁定說明

function print() {console.log(this);
}print.myCall('abc'); // this → String 對象:new String('abc')

值類型(如字符串、數字)在傳入時會被自動裝箱為對象類型。


🚧 七、邊界情況優化建議

  • 如果 contextnullundefined,原生 call 會將 this 指向全局對象(非嚴格模式),或 undefined(嚴格模式);

  • 也可以通過判斷加以處理:

context = context ?? window;

🎯 八、面試高頻拓展:call vs apply vs bind

方法名作用參數傳入方式是否立即執行
call改變 this 并執行函數參數列表? 是
apply改變 this 并執行函數參數數組? 是
bind改變 this,返回新函數參數列表? 否(需手動執行)

📎 九、小結

手動實現 call 的過程并不復雜,但卻是理解 JavaScript 中函數和 this 機制的關鍵一步。建議掌握以下重點:

  • this 的綁定原理(對象調用 vs 普通調用)

  • 值類型的自動裝箱

  • 如何通過函數掛載 + Symbol 解決屬性污染

  • 面試中可以延伸講解 applybind 的區別


🎁 十、完整源碼

Function.prototype.myCall = function (context = window, ...args) {if (typeof context !== 'object' && typeof context !== 'function') {context = new Object(context);}const fnKey = Symbol();context[fnKey] = this;const result = context[fnKey](...args);delete context[fnKey];return result;
};

如果你覺得這篇文章有幫助,歡迎點贊 👍 收藏 ? 評論 💬 交流~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/91475.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/91475.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/91475.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Go語言中的盲點:競態檢測和互斥鎖的錯覺

🧠 Go語言中的盲點:競態檢測和互斥鎖的錯覺 使用 -race 就能發現所有并發問題?加了 mutex 就萬無一失? 這篇文章揭示了 Go 并發編程中的一個“危險盲區” —— 互斥鎖并不能總能保護你免受數據競爭的影響,尤其是在 -ra…

從文件到文件描述符:理解程序與文件的交互本質

一、理解文件 拋一個概念: 文件 內容 屬性。 1. 那么,空文件有大小嗎?答案是有的。因為空文件指的是文件內容為空,文件屬性也要占據大小啊。 將來對文件操作,無非分為兩類: 1.對文件內容做修改。 2.對文件…

優化算法專欄——閱讀導引

前言 提醒: 文章內容為方便作者自己后日復習與查閱而進行的書寫與發布,其中引用內容都會使用鏈接表明出處(如有侵權問題,請及時聯系)。 其中內容多為一次書寫,缺少檢查與訂正,如有問題或其他拓展…

[ The Missing Semester of Your CS Education ] 學習筆記 Vim篇

“Writing English words and writing code are very different activities. When programming, you spend more time switching files, reading, navigating, and editing code compared to writing a long stream.” —— < The Missing Semester of Your CS Education &g…

Linux 系統中定時執行指定命令 crontab 定時任務配置

crontab 定時任務配置是 Linux/Unix 系統中用于自動、周期性執行指定命令或腳本的工具&#xff0c;相當于系統的 “定時鬧鐘”。它可以讓系統在預設的時間&#xff08;如每天凌晨、每周一、每月 1 號等&#xff09;自動完成重復性工作&#xff0c;無需人工干預。自動化運維定期…

[ Leetcode ]---快樂數

題目鏈接 Leetcode快樂數 題目描述 如下圖&#xff1a; 題目解析&#xff1a; 1.雙指針法 算法核心思路 判斷快樂數的關鍵挑戰是如何檢測是否進入無限循環。這里使用了快慢指針法&#xff08;Floyd 循環檢測算法&#xff09;&#xff0c;這是一種高效檢測循環的技巧&#…

智慧社區構建——2

1.實現Token校驗## Token校驗URLjson GET /checkToken 參數json HttpServletRequest request 返回json {"msg": "操作成功","code": 200,"status": "ok" }{"msg": "操作成功","code": 200,&q…

K-Means聚類:當數據沒有標簽時,如何讓計算機自動“物以類聚”?

K-Means聚類&#xff1a;當數據沒有標簽時&#xff0c;如何讓計算機自動“物以類聚”&#xff1f;&#x1f44b; 大家好&#xff0c;我是小瑞瑞&#xff01;歡迎回到我的專欄&#xff01; 在我們之前的旅程中&#xff0c;解決的問題大多都有一個明確的“目標”&#xff0c;比如…

萬事皆可用 GeeLark AI

在今年4月&#xff0c;GeeLark AI 全面接入 DeepSeek AI 大模型&#xff0c;你可以在獨立窗口中便捷地使用 GeeLark AI。除了幫助你編寫文案等基礎內容&#xff0c;在使用 GeeLark 過程中&#xff0c;如果遇到問題&#xff0c;也可以通過詢問 GeeLark AI&#xff0c;及時獲取幫…

3D 高保真處理:聲網讓游戲聲音隨角色動作變化

傳統游戲的聲音體驗像老式收音機&#xff0c;不管聲源位置、距離和障礙物&#xff0c;僅靠左右聲道機械調音量&#xff0c;毫無方向感和空間感&#xff0c;如同蒙眼聽聲辨位。射擊游戲中敵人從左邊來&#xff0c;耳機卻兩邊同響且音量相近&#xff0c;讓人暈頭轉向&#xff1b;…

Nestjs框架: 請求生命周期與應用生命周期

概述 在 NestJS 框架中&#xff0c;中間件&#xff08;Middleware&#xff09;、管道&#xff08;Pipes&#xff09;、過濾器&#xff08;Filters&#xff09;、攔截器&#xff08;Interceptors&#xff09; 均屬于請求處理流程的核心組件&#xff0c;它們共同構成了 NestJS 的…

Nastool+cpolar:群暉NAS用戶的全場景影音自由方案

文章目錄前言1. 本地搭建Nastool2. nastool基礎設置3. 群暉NAS安裝內網穿透工具4. 配置公網地址小結5. 配置固定公網地址**第二版&#xff1a;技術整合與效率提升導向****第二版&#xff1a;技術整合與效率提升導向****第二版&#xff1a;技術整合與效率提升導向**Nastool與cpo…

從零開始:Kaggle 競賽實戰入門指南

一、Kaggle社區概述 Kaggle 是全球最大的數據科學和機器學習社區&#xff0c;由Anthony Goldbloom于2010年創立&#xff0c;2017年被Google收購。平臺專注于數據科學競賽、開源數據集共享、協作編程以及技能學習&#xff0c;吸引了從初學者到專業數據科學家的廣泛用戶群體。 …

sqli-labs:Less-16關卡詳細解析

1. 思路&#x1f680; 本關的SQL語句為&#xff1a; $uname".$uname."; $passwd".$passwd."; $sql"SELECT username, password FROM users WHERE username($uname) and password($passwd) LIMIT 0,1";注入類型&#xff1a;字符串型&#xff08;…

Lipschitz連續函數

Lipschitz function 一、說明 在數學分析中&#xff0c;Lipschitz連續性以德國 數學家 魯道夫利普希茨 (Rudolf Lipschitz)的名字命名&#xff0c;是函數一致連續性的強形式。直觀地說&#xff0c;Lipschitz連續函數的變化速度有限&#xff1a;存在一個實數&#xff0c;使得對于…

Dynamics 365 business central 與Shopify集成

Dynamics 365 Business Central&#xff08;簡稱 D365 BC&#xff09; 與 Shopify 的集成&#xff0c;能幫助企業實現前端電商平臺&#xff08;Shopify&#xff09;與后端 ERP 系統&#xff08;Business Central&#xff09;之間的無縫數據同步&#xff0c;是一種典型的 ERP 與…

TCP RTO 與丟包檢測

TCP RTO 是它 40 多年前唯一丟包檢測策略&#xff0c;也是當前最后的丟包檢測兜底策略&#xff0c;它幾乎從沒變過。 有個咨詢挺有趣&#xff0c;以其案例為背景寫篇隨筆。大致意思是&#xff0c;嫌 TCP RTO 太大&#xff0c;游戲場景丟包卡頓怎么辦&#xff1f;我提供了幾行代…

安裝php和配置環境變量

為了簡單方便&#xff0c;先下載vscode然后下載對應的php安裝包&#xff0c;然后配置環境變量&#xff0c;然后點擊運行即可下載對應版本的php&#xff0c;這個版本湊合用然后下載完之后解壓配置環境變量搜索環境變量將路徑添加到環境變量中然后打開vscode添加變量具體看實際路…

Rabbit MQ的消息模式-Java原生代碼

一.簡單模式1.1.核心邏輯生產者 → 隊列 → 單個消費者&#xff08;1:1 直連&#xff09;&#xff0c;消息被消費后自動從隊列刪除。1.2.關鍵特性無交換器&#xff08;其實使用的是默認交換機不是顯示指定&#xff09;&#xff0c;直接指定隊列 消息默認自動確認&#xff08;au…

【lucene】使用docvalues的案例

下面給出一段 可直接跑通 的 Lucene 8.5.0 示例代碼&#xff0c;演示如何1. 建索引時為兩個字段啟用 DocValues&#xff08;一個 NumericDocValues&#xff0c;一個 SortedDocValues&#xff09;&#xff1b; 2. 用 IndexSearcher 按 DocValues 排序&#xff1b; 3. 用 Facet…