約面了,放輕松,好好面
盲點
基礎知識
Function 和 Object 都是函數,而函數也是對象。
Object.prototype 是幾乎所有對象的原型鏈終點(其 proto 是 null)。
Function.prototype 是所有函數的原型(包括 Object 和 Function 自身)。
Object.proto === Function.prototype (因為 Object 是個構造函數,是函數)
Function.proto === Function.prototype (Function 自身也是函數)
Function.prototype 本身也是一個對象,它的 proto 指向 Object.prototype。
Function.prototype.proto === Object.prototype
CSS
計算機網絡
框架
react版本
react 18
React 18 的并發渲染通過可中斷的任務調度和優先級控制,大幅提升了復雜應用的響應流暢度。新 Hook(如 useTransition、useDeferredValue)為開發者提供了優化工具。??自動批處理??減少了渲染次數,??流式 SSR?? 和 ??選擇性 Hydration?? 改善了首屏性能。升級時注意使用 createRoot 并充分測試嚴格模式下的警告。
并發:渲染任務可中斷/恢復,根據優先級調度(如用戶交互 > 數據加載),避免界面卡頓。
與防抖/節流的區別:防抖和節流是通過延遲執行來減少操作頻率。過渡更新是立即執行更新邏輯,但延遲其渲染的優先級和提交,并且這個過程是可中斷的。過渡更新通常能提供更流暢的體驗。
要使用 startTransition,必須使用 ReactDOM.createRoot 來啟用并發模式,而不是舊的 ReactDOM.render
??理解并善用 StrictMode??
:開發
環境下,<React.StrictMode>會故意雙重調用某些方法(包括 useEffect)以幫助發現副作用中的錯誤
。確保你的 useEffect邏輯具有??冪等性??(多次執行結果相同)
或清理函數能正確取消副作用。如果僅為調試,可暫時注釋 StrictMode,但生產環境不應受影響
rEACTnATIVE
Git
項目
手撕
循環引用
function hasCircularReference(obj, visited = new WeakSet()) {//Set VS WeakSet:// 1.解除不必要的引用:在不需要時,手動解除對象之間的引用可以幫助垃圾回收器更快地回收內存。//// 2.使用弱引用:在ES6中,引入了WeakMap和WeakSet,它們允許創建對對象的弱引用。這些引用不會阻止垃圾回收器回收對象。//// 3.內存分析工具:使用Chrome開發者工具中的內存分析工具可以幫助你檢測內存泄漏和不必要的循環引用。// 如果對象是null或undefined,或者已經訪問過,則返回falseif (!obj || visited.has(obj)) {return false;}// 將當前對象標記為已訪問!!visited.add(obj);// 遍歷對象的所有可枚舉屬性for (let key in obj) {if (obj.hasOwnProperty(key)) {let value = obj[key];// 如果屬性值是對象,則遞歸檢查if (typeof value === 'object' && value !== null) {// 如果在已訪問的對象中找到了當前屬性值,則說明存在循環引用if (visited.has(value)) {return true;}// 遞歸檢查屬性值!!!if (hasCircularReference(value, visited)) {return true;}}}}// 如果沒有找到循環引用,則返回falsereturn false;}
大數相加(含小數)
function addLargeNumbers(num1, num2) {// 分離整數與小數部分let parts1 = num1.toString().trim().split('.');let parts2 = num2.toString().trim().split('.');let int1 = parts1[0] || '0';let int2 = parts2[0] || '0';let dec1 = parts1[1] || '0';let dec2 = parts2[1] || '0';// 對齊小數部分:在較短的小數后補0let maxDecLength = Math.max(dec1.length, dec2.length);dec1 = dec1.padEnd(maxDecLength, '0');dec2 = dec2.padEnd(maxDecLength, '0');// 處理小數部分相加let decResult = addIntegerParts(dec1, dec2);let decimalCarry = 0;// 如果小數部分相加后長度超過最大長度,說明有向整數位的進位if (decResult.length > maxDecLength) {decimalCarry = parseInt(decResult[0]); // 提取進位值decResult = decResult.substring(1); // 保留剩余小數部分}// 處理整數部分相加(加上小數部分的進位)let intResult = addIntegerParts(int1, int2, decimalCarry);// 組合結果if (decResult === '0') {return intResult; // 沒有小數部分時直接返回整數} else {return intResult + '.' + decResult;}
}// 輔助函數:處理整數部分相加(可處理額外進位)
function addIntegerParts(str1, str2, extraCarry = 0) {let arr1 = str1.split('').map(Number);let arr2 = str2.split('').map(Number);let i = arr1.length - 1;let j = arr2.length - 1;let result = [];let carry = extraCarry; // 初始化進位(可能來自小數部分)while (i >= 0 || j >= 0 || carry > 0) {const val1 = i >= 0 ? arr1[i] : 0;const val2 = j >= 0 ? arr2[j] : 0;const sum = val1 + val2 + carry;result.push(sum % 10); // 將當前位添加到數組末尾carry = Math.floor(sum / 10);i--;j--;}// 反轉數組并轉換為字符串(避免使用 unshift 提升性能)return result.reverse().join('');
}// 測試示例
console.log(addLargeNumbers("123.45", "67.8")); // 輸出 "191.25"
console.log(addLargeNumbers("0.999", "0.002")); // 輸出 "1.001"
console.log(addLargeNumbers("100.00", "200.00")); // 輸出 "300"(自動去除多余小數位)
class EventEmitter {constructor() {this.events = new Map(); // 使用Map存儲事件和對應的監聽器列表}// 訂閱事件on(eventName, listener) {if (!this.events.has(eventName)) {this.events.set(eventName, []);}this.events.get(eventName).push(listener);return this; // 支持鏈式調用}// 發布事件emit(eventName, ...args) {const listeners = this.events.get(eventName);if (listeners) {// 復制一份數組,防止在回調函數中取消監聽導致迭代異常listeners.slice().forEach(listener => {listener.apply(this, args);});}return this;}// 取消訂閱off(eventName, listenerToRemove) {const listeners = this.events.get(eventName);if (listeners) {// 過濾掉要移除的監聽器this.events.set(eventName, listeners.filter(listener => listener !== listenerToRemove));}return this;}
}// 使用示例
const emitter = new EventEmitter();
const callback = (data) => console.log('Event received:', data);
emitter.on('myEvent', callback);
emitter.emit('myEvent', { message: 'Hello!' }); // 輸出: Event received: { message: 'Hello!' }
emitter.off('myEvent', callback);
emitter.emit('myEvent', 'This will not be logged'); // 無輸出
真題