JS 手撕題高頻考點

前端面試中,JS 手撕題是高頻考點,主要考察 編程能力、算法思維、JS 核心知識。以下是最常見的手撕題分類 + 代碼示例


目錄

    • 📌 1. 手寫函數柯里化
    • 📌 2. 手寫 `debounce`(防抖)
    • 📌 3. 手寫 `throttle`(節流)
    • 📌 4. 手寫深拷貝
    • 📌 5. 手寫 `new` 操作符
    • 📌 6. 手寫 `call` / `apply` / `bind`
    • 📌 7. 手寫 `Promise.all`
    • 📌 8. 實現 LRU 緩存
    • 📌 9. 手寫 `instanceof`
    • 📌 10. 數組去重

📌 1. 手寫函數柯里化

題目:實現一個 curry(fn) 函數

function curry(fn, ...args) {return args.length >= fn.length? fn(...args): (...nextArgs) => curry(fn, ...args, ...nextArgs);
}// 示例函數
function sum(a, b, c) {return a + b + c;
}const curriedSum = curry(sum);
console.log(curriedSum(1)(2)(3)); // 6
console.log(curriedSum(1, 2)(3)); // 6

📌 2. 手寫 debounce(防抖)

題目:實現 debounce(fn, delay)

function debounce(fn, delay) {let timer;return function (...args) {clearTimeout(timer);timer = setTimeout(() => fn.apply(this, args), delay);};
}// 示例:輸入框搜索
const search = debounce(() => console.log("搜索 API 請求"), 500);
document.getElementById("searchInput").addEventListener("input", search);

📌 3. 手寫 throttle(節流)

題目:實現 throttle(fn, delay)

function throttle(fn, delay) {let lastTime = 0;return function (...args) {const now = Date.now();if (now - lastTime >= delay) {fn.apply(this, args);lastTime = now;}};
}// 示例:鼠標滾動觸發
const handleScroll = throttle(() => console.log("滾動中..."), 1000);
window.addEventListener("scroll", handleScroll);

📌 4. 手寫深拷貝

題目:實現 deepClone(obj)

function deepClone(obj, map = new WeakMap()) {if (typeof obj !== "object" || obj === null) return obj;if (map.has(obj)) return map.get(obj); // 處理循環引用let clone = Array.isArray(obj) ? [] : {};map.set(obj, clone);for (let key in obj) {if (obj.hasOwnProperty(key)) {clone[key] = deepClone(obj[key], map);}}return clone;
}// 示例
const obj = { a: 1, b: { c: 2 } };
const copy = deepClone(obj);
console.log(copy);

📌 5. 手寫 new 操作符

題目:實現 myNew(fn, ...args)

function myNew(fn, ...args) {const obj = Object.create(fn.prototype); // 創建空對象并繼承構造函數原型const result = fn.apply(obj, args); // 執行構造函數return result instanceof Object ? result : obj; // 處理返回值
}// 示例
function Person(name) {this.name = name;
}
const p = myNew(Person, "Alice");
console.log(p.name); // Alice

📌 6. 手寫 call / apply / bind

? 手寫 call

Function.prototype.myCall = function (context, ...args) {context = context || window;const fnKey = Symbol();context[fnKey] = this;const result = context[fnKey](...args);delete context[fnKey];return result;
};// 示例
function greet() {console.log(`Hello, ${this.name}`);
}
const obj = { name: "Alice" };
greet.myCall(obj); // Hello, Alice

? 手寫 apply

Function.prototype.myApply = function (context, args = []) {context = context || window;const fnKey = Symbol();context[fnKey] = this;const result = context[fnKey](...args);delete context[fnKey];return result;
};

? 手寫 bind

Function.prototype.myBind = function (context, ...args) {const self = this;return function (...innerArgs) {return self.apply(context, [...args, ...innerArgs]);};
};// 示例
const boundFn = greet.myBind(obj);
boundFn(); // Hello, Alice

📌 7. 手寫 Promise.all

題目:實現 myPromiseAll(promises)

function myPromiseAll(promises) {return new Promise((resolve, reject) => {let results = [];let count = 0;if (promises.length === 0) resolve([]);promises.forEach((p, index) => {Promise.resolve(p).then(value => {results[index] = value;count++;if (count === promises.length) resolve(results);},error => reject(error));});});
}// 示例
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const p3 = new Promise(resolve => setTimeout(() => resolve(3), 1000));myPromiseAll([p1, p2, p3]).then(console.log); // [1, 2, 3]

📌 8. 實現 LRU 緩存

題目:設計一個 LRUCache

class LRUCache {constructor(capacity) {this.capacity = capacity;this.cache = new Map();}get(key) {if (!this.cache.has(key)) return -1;let value = this.cache.get(key);this.cache.delete(key);this.cache.set(key, value);return value;}put(key, value) {if (this.cache.has(key)) this.cache.delete(key);this.cache.set(key, value);if (this.cache.size > this.capacity) {this.cache.delete(this.cache.keys().next().value); // 刪除最早的鍵}}
}// 示例
const cache = new LRUCache(2);
cache.put(1, "A");
cache.put(2, "B");
console.log(cache.get(1)); // A
cache.put(3, "C"); // 淘汰 key=2
console.log(cache.get(2)); // -1

📌 9. 手寫 instanceof

題目:實現 myInstanceOf(obj, constructor)

function myInstanceOf(obj, constructor) {let proto = Object.getPrototypeOf(obj);while (proto) {if (proto === constructor.prototype) return true;proto = Object.getPrototypeOf(proto);}return false;
}// 示例
console.log(myInstanceOf([], Array)); // true
console.log(myInstanceOf({}, Array)); // false

📌 10. 數組去重

const uniqueArray = arr => [...new Set(arr)];
console.log(uniqueArray([1, 2, 2, 3])); // [1, 2, 3]

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

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

相關文章

【STM32】知識點介紹一:硬件知識

文章目錄 一、電源引腳簡介二、電平信號三、電路分析 一、電源引腳簡介 VCC、GND、VDD和VSS是電子電路中常見的術語,代表著不同的電源引腳或電壓。 VCC(Voltage at the Common Collector):VCC是指集電極(Collector&am…

3. 列表元素替換

【問題描述】給定一個列表,將列表中所有的偶數替換為0 【輸入形式】輸入一行,包含若干個整數,用空格分隔 【輸出形式】輸出替換后的列表,每個元素用空格分隔 【樣例輸入】1 2 3 4 5 6 7 8 9 10 【樣例輸出】1 0 3 0 5 0 7 0 9…

問題的根源還是解題的方案

周末的早上照例是要早醒 debug 代碼的,仿佛又回到了 2014 年… 古人幾天甚至幾個月不洗澡,不會臭嗎?有沒有可能古人沒有化纖類衣服,且古人的純天然生活環境其身體菌群和現代人不同,古人就像健康的野生動物一樣即使不洗…

虛擬機安裝linux系統無法上網的解決方法

在虛擬環境中運行Linux系統時,有時會遇到網絡連接問題,特別是在使用虛擬機軟件如VMware或VirtualBox時。本文將詳細介紹一種針對“虛擬機安裝Linux系統無法上網”問題的解決方案,以CentOS 6.5為例,適用于其他基于NAT模式的虛擬機環…

子網劃分淺度解析

文章目錄 ip地址的組成不同類型ip地址的范圍子網掩碼默認子網掩碼子網掩碼如何作用的?默認子網掩碼怎么作用? ip地址的組成 ip地址一般寫作4位點分十進制(x.x.x.x),他們由32位二進制組成,每個x由8位二進制…

什么是 SEO(搜索引擎優化)?

您有網站嗎,或者您正在考慮創建一個網站?您想吸引更多人加入您的業務嗎?如果答案是肯定的,那么毫無疑問:SEO 應該是您營銷工作的一部分。這是建立品牌和吸引用戶訪問您的網站的好方法。但它實際上意味著什么呢&#xf…

鴻蒙HarmonyOS NEXT設備升級應用數據遷移流程

數據遷移是什么 什么是數據遷移,對用戶來講就是本地數據的遷移,終端設備從HarmonyOS 3.1 Release API 9及之前版本(單框架)遷移到HarmonyOS NEXT(雙框架)后保證本地數據不丟失。例如,我在某APP…

【現代深度學習技術】現代卷積神經網絡04:含并行連接的網絡(GoogLeNet)

【作者主頁】Francek Chen 【專欄介紹】 ? ? ?PyTorch深度學習 ? ? ? 深度學習 (DL, Deep Learning) 特指基于深層神經網絡模型和方法的機器學習。它是在統計機器學習、人工神經網絡等算法模型基礎上,結合當代大數據和大算力的發展而發展出來的。深度學習最重…

【ESP32】ESP32與MQTT通信:實現傳感器數據監測與設備控制

ESP32與MQTT通信 1 項目概覽2 硬件組成3 MQTT協議解析MQTT協議簡介MQTT核心概念本項目中的MQTT應用 4 MQTT Broker選擇EMQX Broker其他常用MQTT Broker 5 代碼解析初始化與配置MQTT消息處理發布傳感器數據 6 MQTT話題TOPIC設計7 EMQX的優勢在IoT項目中的體現8 MQTT通信流程9 應…

[特殊字符]《Curve DAO 系統學習目錄》

本教程旨在系統學習 Curve DAO 項目的整體架構、核心機制、合約設計、治理邏輯與代幣經濟等內容,幫助開發者全面理解其設計理念及運作方式。 目錄總覽: 1. Curve 項目概覽 ? 1.1 Curve 是什么?主要解決什么問題? ? 1.2 與其他…

每天一篇目標檢測文獻(六)——Part One

今天看的是《Object Detection with Deep Learning: A Review》 目錄 一、摘要 1.1 原文 1.2 翻譯 二、介紹 2.1 信息區域選擇 2.2 特征提取 2.3 分類 三、深度學習的簡要回顧 3.1 歷史、誕生、衰落和繁榮 3.2 CNN架構和優勢 一、摘要 1.1 原文 Due to object dete…

Arthas線上問題診斷器

Arthas是Alibaba開源的java診斷工具 解決問題 這個類從哪個jar 包加載的?為什么會報各種相關的Exception? 遇到問題無法在線上debug,不能直通過加載日志再重新發布 有什么辦法可以監控到JVM的實時運行狀態? …

[Lc5_dfs+floodfill] 簡介 | 圖像渲染 | 島嶼數量

目錄 0.floodfill算法簡介 1.圖像渲染 題解 2.島嶼數量 題解 之前我們在 bfs 中有介紹過[Lc15_bfsfloodfill] 圖像渲染 | 島嶼數量 | 島嶼的最大面積 | 被圍繞的區域,現在我們來看看 dfs 又是如何解決的呢 0.floodfill算法簡介 floodfill算法又叫洪水灌溉或者…

JVM類加載器詳解

文章目錄 1.類與類加載器2.類加載器加載規則3.JVM 中內置的三個重要類加載器為什么 獲取到 ClassLoader 為null就是 BootstrapClassLoader 加載的呢? 4.自定義類加載器什么時候需要自定義類加載器代碼示例 5.雙親委派模式類與類加載器雙親委派模型雙親委派模型的執行…

Chapters 15 16:What Is Architecture?Independence_《clean architecture》notes

What Is Architecture?&Independence **Chapter 15: What Is Architecture?****Key Concepts**:**Code Example: Layered Architecture**: **Chapter 16: Independence****Key Concepts**:**Code Example: Dependency Inversion & Interfaces**: **Combined Example:…

【SPP】RFCOMM 層在SPP中互操作性要求深度解析

藍牙串口協議(SPP)通過 RFCOMM 協議實現 RS232 串口仿真,其互操作性是設備互聯的關鍵。本文基于藍牙核心規范,深度解析 RFCOMM 層的能力矩陣、信號處理、流控機制及實戰開發,結合狀態機、流程圖和代碼示例,…

阻塞式IO與非阻塞IO的區別

阻塞式IO與非阻塞IO的區別 1. 阻塞式IO (Blocking I/O) 定義 當程序發起一個I/O操作(如讀取文件、網絡數據)時,進程會被掛起(阻塞),直到操作完成或超時才會繼續執行后續代碼。在此期間,程序無法…

Gossip協議:分布式系統中的“八卦”傳播藝術

目錄 一、 什么是Gossip協議?二、 Gossip協議的應用 💡三、 Gossip協議消息傳播模式詳解 📚四、 Gossip協議的優缺點五、 總結: 🌟我的其他文章也講解的比較有趣😁,如果喜歡博主的講解方式&…

【C++初階】----模板初階

1.泛型函數 泛型編程:編寫與類型無關的通用代碼,是代碼復用的一種手段。模板是泛型編程的基礎。 2.函數模板 2.1函數模板的概念 函數模板代表了一個函數家族,該函數模板與類型無關,在使用時被參數化,根據實參類型…

git-- github的使用--賬戶和本地連接

以下指令在git 執行bash 流程:先看有沒有密鑰; 沒有的話,在電腦生成密鑰對,公鑰復制到github; 要想使用https,配置令牌,注意令牌有期限問題,連接不了有可能是期限問題 一個電腦對…