首頁 web前端 js教程 LeetCode 的 JavaScript 時代實際上填補了空白

LeetCode 的 JavaScript 時代實際上填補了空白

Dec 16, 2024 pm 04:34 PM

The Gap That LeetCode

大多數程式設計挑戰都會教你解決難題。 LeetCode 的 30 天 JavaScript 學習計畫做了一些不同的事情:它向您展示了拼圖如何變成磚塊,準備好建立現實世界的專案。

這種區別很重要。當您解決典型的演算法問題時,您正在訓練您的思維進行抽象思考。但是,當您實現去抖1函數或建構事件發射器2時,您正在學習真正的軟體是如何運作的。

我自己在應對挑戰時發現了這一點。這種體驗不太像解決腦筋急轉彎問題,而更像考古學——揭示特定的現代 JavaScript 概念。每個部分都重點介紹 JS 的另一個現代功能。

這個學習計畫的奇特之處在於它不會教你 JavaScript。事實上,我相信您需要相當了解 JavaScript 才能從中受益。相反,它教導的是如何使用 JavaScript 來解決實際的工程問題。

考慮 Memoize3 挑戰。從表面上看,它是關於快取函數結果的。但你真正學到的是為什麼像 React 這樣的函式庫需要記憶來有效地處理元件渲染。或以 Debounce1 問題為例 - 這不僅僅是實現延遲;它還涉及延遲。它可以幫助您直接理解為什麼每個現代前端框架、電梯以及基本上任何具有互動式 UI 的系統都需要這種模式。

這種對實用模式而不是語言基礎知識的關注創造了一個有趣的限制;您需要處於以下兩個位置之一才能受益:

  1. 您了解 CS 基礎(尤其是資料結構和演算法)並且熟悉 JavaScript
  2. 您精通 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 是本節中我最喜歡的一個

模式識別,而不是解決問題

讓我們剖析一些問題,以展示該學習計劃的真正價值。

  1. 記憶 (#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
登入後複製
登入後複製
  1. 反跳 (#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
登入後複製

沒有去抖動:


這將進行 10 次 API 呼叫。其中大多數都沒用,因為用戶仍在打字。
// 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 毫秒延遲):


去抖就像告訴你的程式碼:「等到使用者停止執行某些動作 X 毫秒後再實際執行此函數。」
// 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 生態系統的更深入理解。

這就是本學習計畫填補的空白:將理論知識與實務工程智慧連結起來。



  1. 2627。 Debounce(承諾與時間)↩

  2. 2694。事件發射器(類)↩

  3. 2623。 Memoize(函數轉換)↩

  4. 2636。承諾池(獎金)↩

以上是LeetCode 的 JavaScript 時代實際上填補了空白的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

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

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

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

熱門話題

Java教學
1655
14
CakePHP 教程
1414
52
Laravel 教程
1307
25
PHP教程
1254
29
C# 教程
1228
24
神秘的JavaScript:它的作用以及為什麼重要 神秘的JavaScript:它的作用以及為什麼重要 Apr 09, 2025 am 12:07 AM

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

JavaScript的演變:當前的趨勢和未來前景 JavaScript的演變:當前的趨勢和未來前景 Apr 10, 2025 am 09:33 AM

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

JavaScript引擎:比較實施 JavaScript引擎:比較實施 Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

JavaScript:探索網絡語言的多功能性 JavaScript:探索網絡語言的多功能性 Apr 11, 2025 am 12:01 AM

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

Python vs. JavaScript:學習曲線和易用性 Python vs. JavaScript:學習曲線和易用性 Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

如何使用Next.js(前端集成)構建多租戶SaaS應用程序 如何使用Next.js(前端集成)構建多租戶SaaS應用程序 Apr 11, 2025 am 08:22 AM

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

從C/C到JavaScript:所有工作方式 從C/C到JavaScript:所有工作方式 Apr 14, 2025 am 12:05 AM

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

如何安裝JavaScript? 如何安裝JavaScript? Apr 05, 2025 am 12:16 AM

JavaScript不需要安裝,因為它已內置於現代瀏覽器中。你只需文本編輯器和瀏覽器即可開始使用。 1)在瀏覽器環境中,通過標籤嵌入HTML文件中運行。 2)在Node.js環境中,下載並安裝Node.js後,通過命令行運行JavaScript文件。

See all articles