LeetCode 的 JavaScript 時代實際上填補了空白
大多數程式設計挑戰都會教你解決難題。 LeetCode 的 30 天 JavaScript 學習計畫做了一些不同的事情:它向您展示了拼圖如何變成磚塊,準備好建立現實世界的專案。
這種區別很重要。當您解決典型的演算法問題時,您正在訓練您的思維進行抽象思考。但是,當您實現去抖1函數或建構事件發射器2時,您正在學習真正的軟體是如何運作的。
我自己在應對挑戰時發現了這一點。這種體驗不太像解決腦筋急轉彎問題,而更像考古學——揭示特定的現代 JavaScript 概念。每個部分都重點介紹 JS 的另一個現代功能。
這個學習計畫的奇特之處在於它不會教你 JavaScript。事實上,我相信您需要相當了解 JavaScript 才能從中受益。相反,它教導的是如何使用 JavaScript 來解決實際的工程問題。
考慮 Memoize3 挑戰。從表面上看,它是關於快取函數結果的。但你真正學到的是為什麼像 React 這樣的函式庫需要記憶來有效地處理元件渲染。或以 Debounce1 問題為例 - 這不僅僅是實現延遲;它還涉及延遲。它可以幫助您直接理解為什麼每個現代前端框架、電梯以及基本上任何具有互動式 UI 的系統都需要這種模式。
這種對實用模式而不是語言基礎知識的關注創造了一個有趣的限制;您需要處於以下兩個位置之一才能受益:
- 您了解 CS 基礎(尤其是資料結構和演算法)並且熟悉 JavaScript
- 您精通 CS 理論並且之前接觸過一些 JavaScript
連結電腦科學和軟體工程
學習電腦科學和實踐軟體工程之間會發生一些奇怪的事情。這種轉變感覺就像學習了多年的國際象棋理論,卻發現自己在玩一種完全不同的遊戲 - 規則不斷變化,而且大多數動作都不在任何書本中。
在電腦科學中,您將學習二元樹的工作原理。在軟體工程中,您需要花費數小時來除錯 API,試圖了解回應快取不起作用的原因。從遠處看,這些世界之間的重疊可能看起來比實際上大得多。其中存在差距,這常常會讓電腦科學畢業生在開始職業生涯時感到震驚。不幸的是,大多數教育資源都無法彌補這一點。它們要么純粹是理論性的(「這是快速排序的工作原理」),要么是純粹的實用性(「這是如何部署 React 應用程式」)。
這個 JavaScript 學習計畫的有趣之處並不是它設計得特別好 - 而是它在這些世界之間創造了連結。以記憶問題為例:2623。記憶3。用計算機科學術語來說,它是關於快取計算值的。但實作它會迫使您應對 JavaScript 在物件參考、函數上下文和記憶體管理方面的特殊性。突然,
你不只是在學習演算法 - 你開始理解為什麼像 Redis 這樣的東西存在。
這種風格在整個挑戰中不斷重複。 Event Emitter2 實作不僅僅是教科書觀察者模式 - 您可以將其視為將 V8 引擎從瀏覽器中取出並圍繞它構建 Node.js 的原因,這實際上是有意義的。 Promise Pool4 解決並行執行問題,也就是資料庫需要連線限制的原因。
隱藏課程
本學習計畫中的問題順序不是隨機的。它正在逐層建構現代 JavaScript 的心理模型。
它從閉包開始。並不是因為閉包是最簡單的概念 - 它們非常令人困惑 - 而是因為它們是 JavaScript 管理狀態的基礎。
function createCounter(init) { let count = init; return function() { return count++; } } const counter1 = createCounter(10); console.log(counter1()); // 10 console.log(counter1()); // 11 console.log(counter1()); // 12 // const counter1 = createCounter(10); // when this^ line executes: // - createCounter(10) creates a new execution context // - local variable count is initialized to 10 // - a new function is created and returned // - this returned function maintains access // to the count variable in its outer scope // - this entire bundle // (function (the inner one) + its access to count) // is what we call a closure
這種模式是 JavaScript 中所有狀態管理的種子。一旦你了解了這個計數器的工作原理,你就了解了 React 的 useState 在幕後是如何運作的。您了解為什麼模組模式會出現在 ES6 之前的 JavaScript 中。
然後計畫轉向功能轉換。這些教你函數裝飾——函數包裝其他函數以修改它們的行為。這不僅僅是一個技術技巧;這就是 Express 中間件的工作方式,React 高階組件的工作方式,
以及 TypeScript 裝飾器的工作原理。
當您遇到非同步挑戰時,您不僅僅是在學習 Promise,您還會發現 JavaScript 最初需要它們的原因。 Promise Pool4 問題不是在教你一個創新的、古怪的 JS 概念;而是在教你一個創新的、古怪的 JS 概念。它向您展示了為什麼每個資料庫引擎中都存在連接池。
以下是學習計畫各部分與現實世界軟體工程概念的粗略映射:
- 關閉 → 狀態管理
- 基本陣列轉換 → 基本技能(輔助);實際範例:資料操作
- 函數轉換 → 中間件模式
- 承諾與時間 ->非同步控制流
- JSON ->基礎技能(輔助);實例:資料序列化、API通訊
- 類別(特別是在事件發射器的上下文中)→訊息傳遞系統
- 獎金(高級鎖定)->可能包含在上述部分中的更難的挑戰的組合; Promise Pool4 是本節中我最喜歡的一個
模式識別,而不是解決問題
讓我們剖析一些問題,以展示該學習計劃的真正價值。
- 記憶 (#2623)
考慮 Memoize 挑戰。我喜歡它的原因是(我能想出的)最好的解決方案
非常簡單,就好像程式碼本身在溫和地告訴您它的作用(不過,我添加了一些註釋)。
無論如何,這並不會讓 #2623 成為一個簡單的問題。我之前需要兩次迭代才能讓它變得如此乾淨:
function createCounter(init) { let count = init; return function() { return count++; } } const counter1 = createCounter(10); console.log(counter1()); // 10 console.log(counter1()); // 11 console.log(counter1()); // 12 // const counter1 = createCounter(10); // when this^ line executes: // - createCounter(10) creates a new execution context // - local variable count is initialized to 10 // - a new function is created and returned // - this returned function maintains access // to the count variable in its outer scope // - this entire bundle // (function (the inner one) + its access to count) // is what we call a closure
- 反跳 (#2627)
想像一下你在電梯裡,有人瘋狂地重複按下「關門」按鈕。
按 按 按 按 按
按按
沒有去抖:電梯會在每按一次門時嘗試關門,導致門機構工作效率低下,甚至可能損壞。
防手震:電梯會等待,直到人停止按下一定時間(假設 0.5 秒),然後才真正嘗試關門。這樣效率就高多了。
這是另一個情況:
/** * @param {Function} fn * @return {Function} */ function memoize(fn) { // Create a Map to store our results const cache = new Map(); return function(...args) { // Create a key from the arguments const key = JSON.stringify(args); // If we've seen these arguments before, return cached result if (cache.has(key)) { return cache.get(key); } // Otherwise, calculate result and store it const result = fn.apply(this, args); cache.set(key, result); return result; } } const memoizedFn = memoize((a, b) => { console.log("computing..."); return a + b; }); console.log(memoizedFn(2, 3)); // logs "computing..." and returns 5 console.log(memoizedFn(2, 3)); // just returns 5, no calculation console.log(memoizedFn(3, 4)); // logs "computing..." and returns 7 // Explanantion: // It's as if our code had access to an external database // Cache creation // const cache = new Map(); // - this^ uses a closure to maintain the cache between function calls // - Map is perfect for key-value storage // Key creation // const key = JSON.stringify(args); // - this^ converts arguments array into a string // - [1,2] becomes "[1,2]" // - we are now able to use the arguments as a Map key // Cache check // if (cache.has(key)) { // return cache.get(key); // } // - if we've seen these arguments before, return cached result; // no need to recalculate
沒有去抖動:
// typing "javascript" 'j' -> API call 'ja' -> API call 'jav' -> API call 'java' -> API call 'javas' -> API call 'javasc' -> API call 'javascr' -> API call 'javascri' -> API call 'javascrip' -> API call 'javascript' -> API call
帶去抖動(300 毫秒延遲):
// typing "javascript" 'j' 'ja' 'jav' 'java' 'javas' 'javasc' 'javascr' 'javascri' 'javascrip' 'javascript' -> API call (only one call, 300ms after user stops typing)
這是 LeetCode #2627 的解決方案:
- 現實世界中其他常見的去抖動用例(搜尋列除外):
提交按鈕(防止重複提交)
出了什麼問題
我希望,從這篇文章整體正面的基調來看,我對JS 30天的看法現在已經清晰了。但是沒有任何教育資源是完美的,而且,當涉及到局限性時,誠實是有價值的。這個學習計畫有幾個盲點值得檢視。
首先,學習計畫假設有一定程度的先驗知識。
如果您還不太熟悉 JavaScript,那麼有些挑戰可能會令人難以承受。這可能會讓初學者感到沮喪,因為他們可能對學習計劃有其他期望。
其次,挑戰是以孤立的方式呈現的。
這在一開始是有道理的,但隨著計劃的進展,你可能會感到失望。現實世界的問題通常需要結合多種模式和技術。研究計劃可以受益於更全面的挑戰,這些挑戰需要一起使用多個概念(例外:我們在整個計劃中都使用了閉包)。這些很適合放在獎勵部分(已經為高級用戶保留)。
最後,這群挑戰的主要弱點在於其概念解釋。來自競爭性節目,
我習慣在問題陳述中明確新術語和概念的定義。然而,LeetCode 的描述通常過於複雜——理解他們對去抖函數的解釋比實現實際的解決方案更難。
儘管有缺點,該學習計劃仍然是理解現代 JavaScript 的寶貴資源。
30 天之後
理解這些模式只是個開始。
真正的挑戰是識別何時以及如何將它們應用到生產代碼中。這是我在野外遇到這些模式後發現的。
首先,這些模式很少是單獨出現。真實的程式碼庫以挑戰無法探索的方式將它們組合起來。考慮一個從頭開始實現的搜尋功能。您可能會發現自己使用:
- 輸入處理的反跳
- 結果緩存的記憶
- 承諾 API 呼叫逾時
- 用於搜尋狀態管理的事件發射器
所有這些模式相互作用,創造了複雜性,沒有任何單一的挑戰能讓您做好準備。但是,在自己實現了每個部分之後,您將大致了解整個實現的運作方式。
與直覺相反,您將獲得的最有價值的技能不是實現這些模式 - 而是在其他人的程式碼中識別它們。
最後的想法
完成本學習計畫後,程式設計面試並不是您認識這些模式的唯一地方。
您會在開源程式碼、同事的拉取請求中發現它們,並且可能會開始在您過去的專案中註意到它們。您以前可能已經實現了它們,甚至沒有意識到。最重要的是,您將會明白它們為何存在。
最初的解謎轉變為對現代 JavaScript 生態系統的更深入理解。
這就是本學習計畫填補的空白:將理論知識與實務工程智慧連結起來。
-
2627。 Debounce(承諾與時間)↩
-
2694。事件發射器(類)↩
-
2623。 Memoize(函數轉換)↩
-
2636。承諾池(獎金)↩
以上是LeetCode 的 JavaScript 時代實際上填補了空白的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

Python和JavaScript開發者的薪資沒有絕對的高低,具體取決於技能和行業需求。 1.Python在數據科學和機器學習領域可能薪資更高。 2.JavaScript在前端和全棧開發中需求大,薪資也可觀。 3.影響因素包括經驗、地理位置、公司規模和特定技能。

學習JavaScript不難,但有挑戰。 1)理解基礎概念如變量、數據類型、函數等。 2)掌握異步編程,通過事件循環實現。 3)使用DOM操作和Promise處理異步請求。 4)避免常見錯誤,使用調試技巧。 5)優化性能,遵循最佳實踐。

實現視差滾動和元素動畫效果的探討本文將探討如何實現類似資生堂官網(https://www.shiseido.co.jp/sb/wonderland/)中�...

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

如何在JavaScript中將具有相同ID的數組元素合併到一個對像中?在處理數據時,我們常常會遇到需要將具有相同ID�...

zustand異步操作中的數據更新問題在使用zustand狀態管理庫時,經常會遇到異步操作導致數據更新不及時的問題。 �...
