JavaScript演算法:氣泡排序

氣泡排序是一種簡單的排序演算法,但它的效率相對較低,最壞的情況下的時間複雜度為 O(n^2)。 儘管如此,學習它是值得的。 我們遍歷一個數組,將每個元素與其旁邊的元素進行比較。 如果右邊的元素比較小,我們就交換它們的位置。 以下是我們的實現: const bubbleSort = (originalArray) => { let swapped = false const a = [...originalArray] for (let i = 1; i < a.length - 1; i++) { swapped = false for (let j = 0; j < a.length - i; j++) { if (a[j + 1] < a[j]) { ;[a[j], a[j + 1]] = [a[j + 1], a[j]] swapped = true } } if (!swapped) { return a } } return a } 你可以看到,O(n^2) 是因為我們對數組進行了兩次循環,以檢查是否需要將項目與右邊的項目交換位置。...

JavaScript演算法:線性搜索

線性搜索,也被稱為順序搜索或簡單搜索,是最基本的搜索演算法。給定一個資料結構,例如一個數組,我們通過查看所有元素來搜索某個項目,直到找到為止。 它的實現非常簡單: const linearSearch = (list, item) => { for (const [i, element] of list.entries()) { if (element === item) { return i; } } }; 這會返回我們要查找的項目的索引。例如: linearSearch(['a', 'b', 'c', 'd'], 'd'); //3(索引從0開始) 如果我們查找的是’a’,該演算法只會查看第一個元素並返回,所以速度非常快。 但是如果我們查找的是最後一個元素,該演算法需要遍歷整個數組。計算大O值時,我們始終考慮最壞情況。 因此,該演算法的時間複雜度(演算法複雜度)為O(n)。

JavaScript算法:選擇排序

假設我們有一個數字陣列,我們想要按照元素大小對其進行排序。 你可以有一個物件的陣列,並且可以比較物件的屬性,例如按年齡排序或按姓氏的字母順序排序。細節並沒有改變。 我們的做法是:我們選擇第一個項目。然後我們將其與第二個項目進行比較。如果第二個項目比較小,我們將其與第一個項目交換位置。然後,我們將這個第一個項目與陣列中的每個項目進行比較。 一旦我們知道我們有最小的項目,我們將切換到第二個元素,並將其與陣列中的每個項目進行比較,忽略索引為0,因為我們已經知道那是最小值。以此類推,直到陣列的結尾。 正如你所見,這個演算法非常昂貴。它不僅在陣列的每個項目上進行迭代:對於每個項目,它還會再次迭代陣列。 它的時間複雜度是O(n^2)。請注意,嚴格來說,我們比較的項目數量不斷變小,但這在複雜度的大O表示法中並不意味著任何事情。 以下是我們實現的選擇排序算法。 const selectionSort = (originalList) => { //首先我們將陣列複製一份,以避免修改原始陣列,因為在JS中,物件是按引用傳遞的 const list = [...originalList] const len = list.length for (let i = 0; i < len; i++) { let min = i for (let j = i + 1; j < len; j++) { if (list[min] > list[j]) { min = j } } if (min !== i) { //找到了一個新的最小值。與當前元素交換位置 ;[list[i], list[min]] = [list[min], list[i]] } } return list } const listOfNumbers = [1, 6, 3, 4, 5] console....

JavaScript算術運算子

在任何編程語言中,進行數學運算和計算是一個非常常見的操作。JavaScript提供了幾個運算子來幫助我們處理數字。 加法 (+) 減法 (-) 除法 (/) 餘數 (%) 乘法 (*) 指數運算 (**) 遞增運算子 (++) 遞減運算子 (--) 一元否定運算 (-) 一元正運算 (+) 加法 (+) const three = 1 + 2 const four = three + 1 如果使用字符串,+ 運算子也可以用於字符串拼接,所以要注意: const three = 1 + 2 three + 1 // 4 'three' + 1 // three1 減法 (-) const two = 4 - 2 除法 (/) 返回第一個運算元和第二個運算元的商: const result = 20 / 5 //result === 4 const result = 20 / 7 //result === 2....

JavaScript數組資料結構

數組是任何編程語言中最基本的資料結構。 數組在大多數(如果不是所有)編程語言中都是內建的。 讓我們來談談數組在大多數低級編程語言(如C語言)中的表示方式:它們表示計算機內存中一組連續的存儲單元。 從一個內存單元開始(如果你想的話,可以將這些單元想象成電子表格中的單元格),我們可以通過使用10個連續的存儲單元來創建一個包含10個插槽的數組。 這使我們能夠進行諸如通過知道第一個插槽(# 0)的內存地址,然後簡單地將 2 添加到該地址來訪問插槽#2之類的操作。 在JavaScript中,我們在更高層次上進行工作,數組的工作方式也不同。我們無法像C或其他低級語言那樣直接訪問內存,因此我們無法進行這種類型的數組數學運算。 低級語言中的數組只能存儲一種特定的數據類型,因此我們可以預先計算出數組將占用多少內存,以便將其安全地存儲在可以容納它的計算機內存中。 在JavaScript中,數組可以存儲任何類型的數據,並且可以混合使用。我們可以有一個數字,然後是一個物件,然後是另一個數組。 使用以下語法初始化數組: const myArray = [] 或者 const myArray = new Array() 這兩者沒有區別,但我更喜歡使用簡寫語法[]。 在JavaScript中,我們不需要在創建時指定數組大小,但是我們可以這樣做: const myArray = new Array(10) 然後我們可以填充數組的值: let val = 1 for (const [i, v] of myArray.entries()) { myArray[i] = val++ } 您可以使用以下語法引用數組中的第一個項目: myArray[0] (索引從0開始),並且可以通過增加索引號獲取數組中的每個後續項目: myArray[4] //5 myArray[3 + 4] //8 您可以使用以下語法更改任何位置的項目值: myArray[3] = 'Another item' JavaScript中的數組在內部是對象,因此它們具有方法。您可以使用 push方法將一個項目添加到數組的末尾: myArray.push(11) 您可以使用splice()方法(不要與slice()混淆)在任何位置添加項目。 在開頭: myArray.splice(0, 0, 'new item') 在索引3處: myArray.splice(3, 0, 'new item') 您可以使用以下語法從數組的末尾刪除一個項目:...

JavaScript數學庫

Math物件包含了很多與數學有關的工具。本教程將介紹所有這些工具。 Math物件包含了很多與數學有關的工具。 它包含了常數和函數。 常數 項目 說明 Math.E 自然對數的底數e(約等於2.71828) Math.LN10 表示底數為10的自然對數 Math.LN2 表示底數為2的自然對數 Math.LOG10E 表示以10為底的對數的底數值 Math.LOG2E 表示以2為底的對數的底數值 Math.PI 圓周率π(約等於3.14159) Math.SQRT1_2 值為2的平方根的倒數 Math.SQRT2 值為2的平方根 函數 所有這些函數都是靜態的,Math物件無法實例化。 Math.abs() 返回一個數字的絕對值 Math.abs(2.5) //2.5 Math.abs(-2.5) //2.5 Math.acos() 返回操作數的反餘弦值 操作數必須在-1和1之間 Math.acos(0.8) //0.6435011087932843 Math.asin() 返回操作數的反正弦值 操作數必須在-1和1之間 Math.asin(0.8) //0.9272952180016123 Math.atan() 返回操作數的反正切值 Math.atan(30) //1.5374753309166493 Math.atan2() 返回兩個參數的商的反正切值 Math.atan2(30, 20) //0.982793723247329 Math.ceil() 向上取整 Math.ceil(2.5) //3 Math.ceil(2) //2 Math.ceil(2.1) //3 Math.ceil(2.99999) //3 Math.cos() 返回以弧度表示的角度的餘弦值 Math.cos(0) //1 Math.cos(Math.PI) //-1 Math.exp() 返回以Math.E為底,指數為參數的指數函數值 Math.exp(1) //2.718281828459045 Math.exp(2) //7....

JavaScript標記語句

一個關於JavaScript中一個很少使用的功能的教程:標記語句 JavaScript有一個相對較為不知名的功能,它允許你對語句進行標記。 我最近在Svelte中看到這個功能的使用,它用於創建反應式聲明,這些聲明在語句中聲明的變量發生變化時重新計算: $: console.log(variable) 它們還允許使用語句塊,這是JavaScript的另一個特性,它允許你在可以定義語句的地方定義一個塊: $: { console.log(variable) console.log('another thing') //... } 這可能看起來很奇怪,但這是正確的JavaScript。這個語句塊被賦予了$ 標記。 Svelte編譯器在內部使用這個功能來創建反應式聲明。 我從未在其他地方使用過這個功能,但它的主要用例是在不是最近的循環或switch的語句中跳出。 這裡有一個簡單的例子來解釋我的意思。 在這些點中的任何一個位置調用break,都會跳出switch,以避免運行其他case: for (let y = 0; y < 3; y++) { switch (y) { case 0: console.log(0) break case 1: console.log(1) break case 2: console.log(2) break } } 這將正確地輸出0 1 2到控制台。 但是,如果我們想在reache到case 1時跳出for循環呢?這是如何做到的: loop: for (let y = 0; y < 3; y++) { switch (y) { case 0: console.log(0) break case 1: console....

JavaScript範圍

學習JavaScript範圍的基礎知識 範圍是一組定義在編程語言中以確定變量值的規則。 JavaScript使用詞法範圍,這意味著變量的值由其在被寫入時的位置所定義,而不是在其被調用時,這是與另一種替代方式動態範圍不同的事情。 範圍是對程序的部分可見的變量集合。 我們有全局範圍,區塊範圍和函數範圍。如果一個變量在函數或區塊外部定義,它將附加到全局對象並具有全局範圍,這意味著它在程序的每個部分都可用。 var,let和const聲明之間有一個非常重要的區別。 在函數內部定義為var的變量只在該函數內部可見,就像函數參數一樣。 另一方面,在其所在的塊內定義為const或let的變量只在該塊內部可見。 重要的是要理解,塊(由一對花括號標識)不為var定義新的範圍,但對於let和const則有。只有在創建函數時,才為var創建新的範圍,因為var沒有塊範圍,而是函數範圍。 在函數內部,任何在其中定義的var變量在所有函數代碼中都可見,即使該變量在函數結束時聲明,它仍然可以在開頭引用,因為JavaScript在執行代碼之前實際上會將所有變量聲明移動到頂部(這被稱為提升)。為避免混淆,始終在函數開頭聲明var變量。 這就是我的意思。即使你在函數結尾聲明了一個var變量,它的聲明也會被移到頂部: function run() { console.log(`${name}`) var name = 'Flavio' } run() 這將打印出“undefined”,因為實際上發生的是: function run() { var name; console.log(`${name}`) name = 'Flavio' } run() let和const不會“受到”提升的影響。如果在上面的示例中使用它們之一,則會出現錯誤:ReferenceError: name is not defined。 在JavaScript中,父函數的變量也可以在內部函數中使用。內部函數的範圍還包括父函數的範圍,這稱為閉包(我們將在後面更詳細地談論這一點)。 你需要注意一點。在非嚴格模式下,如果你使用未聲明的變量,無論你在哪裡使用,該變量都會附加到全局範圍。這可能是錯誤的根源。所以,在使用變量之前,請確保始終聲明變量。只是要意識到這一點,但這只是預設情況下使用嚴格模式的另一個原因,嚴格模式可以解決這個問題。我們之後再談論嚴格模式。 記住:在具有與全局變量同名的函數(或塊)中定義的任何變量優先於全局變量,遮蔽它。 這將打印undefined: var name = 'Roger' function run() { console.log(`${name}`) var name = 'Flavio' } run() 而這將引發錯誤ReferenceError: name is not defined: let name = 'Roger' function run() { console.log(`${name}`) let name = 'Flavio' } run()

JavaScript還是Python?

我寫了一本關於JavaScript的書,還寫了一本關於Python的書,人們經常問我一個問題,該從哪個開始? 它們都非常適合初學者,並且非常受歡迎。 它們的區別在於你可以用它們做什麼。 它們都是動態且通用的程式語言,但JavaScript在瀏覽器中運行的優勢巨大,所以它在前端開發中被廣泛使用。 Python在數據科學和機器學習的應用中表現出色,有許多針對該領域開發的套件,所以你可以根據這一點來做出決定。 如果你猶豫不決無法做出決定,我建議你學校教授的那種語言,或者是你想要開發的項目所使用的語言。或者是你想要工作的公司所使用的語言。 如果你還是猶豫不決,那就由我來幫你選擇。我會推薦JavaScript,因為我認為它更加靈活,而且可以在瀏覽器中運行這一事實是一個巨大的優勢。

JavaScript還值得學嗎?

對於JS開發人員還有需求嗎?或者JavaScript已經趨於陳舊? 我在Google上搜尋關於JavaScript的問題時,注意到Google在“還有人問”框中建議了一些我認為很有趣的問題: 這些引起了我的注意。 點擊其中一個問題的答案,結果向我確認了我毫不懷疑的觀點。但我對這個話題也有自己的想法,所以我想“讓我寫下來”! 讓我們正確地說吧:JavaScript比以往任何時候都更加活躍。 JavaScript從來沒有像今天這樣受歡迎過。也從來沒有像今天這樣強大過。 當我在90年代末開始學習JS時,絕大多數的開發人員只是用它在聖誕節網站上下雪,顯示警報和對話框,以及做各種奇怪的效果。這樣做很有趣,但只有專業人士才會用它來創建比一個調查更複雜的東西。 當我在2012-2013年認真學習JS時,JS變得更加嚴肅。Gmail、Google Maps和其他厚客戶端應用程序向我們展示了JavaScript所能實現的一切。Node.js當時剛開始變得受歡迎,但實際在生產中使用它的人數仍然有限。 如今,許多人將JavaScript作為他們的第一門並且唯一的編程語言來學習。多年來,他們可能永遠不會學習其他語言,因為我可以說,由於JavaScript是唯一一種能在Web瀏覽器內運行的語言,它是全世界最受歡迎且功能最強大的語言。 如果有人告訴你不同的意見,可能是因為他們最喜歡的編程語言比較不受歡迎,他們希望有一天人們停止使用JS並使用他們所投入了大量精力的語言 :)