金三銀四了,掌握 JS 這 36 個概念,助你一臂之力

前端小智發表於2022-04-02
作者:Mahdhi Rezvi
譯者:前端小智
來源:dmitripavlutin

有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。

本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。

你可能會經常聽到一些人在抱怨 JS 很奇怪,有時甚至是一文不值。 之所以有這種想法,是因為他們不太瞭解 JS 背後的運作方式。 我也覺得 JS 在某些情況處理方式與其它語言不太一樣,但這並不能怪它,它也只是以自己的方式展現給大家而已。

如果,你熱愛一門程式語言,那麼應該就會想深入瞭解並逐個掌握它的概念。

這裡列出了36個JavaScript概念,你需要掌握這些概念才能成為一個更懂 JS 的前端開發者。

1.呼叫堆疊執行

我們都知道堆疊溢位,但是你知道堆疊溢位是由什麼原因導致的嗎? 堆疊溢位是與呼叫堆疊一些操作錯誤相關聯的。

理解了呼叫堆疊,你就會清楚解像是JS 這們的程式語言是如何執行的。

2. 原始資料型別

const foo = "bar";
foo.length; // 3
foo === "bar"; // true

這裡,我們將值bar分配給常量foo時,它屬於原始型別string。 這個每個人都知道。 但是各位少俠想沒想過一個問題,string是基本資料型別,怎麼能呼叫方法了?

奇怪嗎? 不。

這個特性稱為自動裝箱。每當讀取一個基本型別的時候,JS 後臺就會建立一個對應的基本包裝型別物件,從而讓我們能夠呼叫一些方法來操作這些資料。

還是拿上面的例子開始:

const foo = "bar";
foo.length; // 3
foo === "bar"; // true

變數 foo 是一個基本型別值,它不是物件,它不應該有方法。但是 JS 內部為我們完成了一系列處理(即裝箱),使得它能夠呼叫方法,實現的機制如下:

  • 建立String型別的一個例項
  • 在例項上呼叫指定的方法
  • 銷燬這個例項
const foo  = new String("bar");
foo.length
foo === 'bar'
foo = null

通過對原始資料型別有深入的瞭解,我們就應該知道這些“怪異”情況是如何發生的,以及它們背後的邏輯原因。

3.值型別和引用型別

最近,我對“引用傳遞" 在 JS 是怎麼工作的感到困惑。 儘管我知道 C 和 Java 等語言中有“按引用傳遞”“按值傳遞”的概念,但是我不確定它在 JS 中如何工作。

你是否知道分配給 JS 中非原始值的變數對該值的引用? 引用指向儲存值的記憶體位置。。

var arr1 = [1,2,3];
var arr2 = arr1;
arr2.push(10);
console.log(arr2);
//[1, 2, 3, 10]
console.log(arr1);
//[1, 2, 3, 10]

上面的示例中可以看到,對arr2所做的任何修改也將體現在arr1上。 這是因為它們僅儲存值對應的記憶體地址的引用,而非值本身。

通過了解值型別和引用型別的概念,你就會更好地瞭解如何為變數分配值和記憶體引用。

4. 強制型別轉換

這個概念主要解釋了隱式和顯式型別強制之間的區別。 這是前端開發中對 JS 迷惑少數幾個領域之一。 對於隱式強制轉換的概念尤其如此,因為它對不同的資料型別以不同的方式表現。

這是 JS 面試中最常被考的。

Number('789')   // 顯式
+'789'          // 隱式
789 != '456'    // 隱式
9 > '5'         // 隱式
10/null          // 隱式
true | 0        // 隱式

掌握了型別顯隱轉換,恭喜你對 JS 瞭解就進一步了。

5. 比較運算子號 和 typeof 運算子

雙等與三等,它們在大多數情況下在表面上看起來相同並且給出相同的結果,但是,它們有時候可能會給帶來意想不到的錯誤。

為了瞭解這兩親兄弟的區別,我們可以藉助 typeof 來檢視被比較的值的型別。

typeof 3 // "number"
typeof "abc" // "string"
typeof {} // "object"
typeof true // "boolean"
typeof undefined // "undefined"
typeof function(){} // "function"
typeof [] // "object"
typeof null // "object"

6. JavaScript 作用域

作用域是 JS 中一個很重要的尷尬,JS 也一直在不斷完善自己的作用域。 根據Wissam的說法,作用域的簡單定義是,編譯器在需要時查詢變數和函式。

瞭解作用域有助於我們有效地使用JavaScript。 我們還需要了解全域性作用域以及塊和函式作用域,也稱為詞法作用域。 JS 作用域一開始接觸會感到很困惑,但是一旦你瞭解了事情的幕後原理,使用它就會非常令人興奮。

7. 語句和宣告

JavaScript 程式是一系列可執行語句的集合。所謂語句,就是一個可執行的單元,通過該語句的執行,從而實現某種功能。通常一條語句佔一行,並以分號結束。預設情況下,JavaScript 直譯器按照語句的編寫流程依次執行。如果要改變這種預設執行順序,需要使用判斷、迴圈等流程控制語句。

我們應該要知道 語句和宣告 的區別,這對我們全面瞭解 JS 是很有幫助的。

8. 立即呼叫的函式表示式和模組

IIFE: Immediately Invoked Function Expression,意為立即呼叫的函式表示式,也就是說,宣告函式的同時立即呼叫這個函式。它主要用於避免汙染全域性作用域。 後來,引入了ES6模組,為避免全域性作用域的汙染提供了一種標準方法,儘管有人認為它不是IIFE的直接替代。

通過理解IIFE和模組,你可以構建較少由於全域性空間處理不當而導致的錯誤的應用程式。當然,使用模組,我們還可以做很多事情。

大家都說簡歷沒專案寫,我就幫大家找了一個專案,還附贈【搭建教程】

9.訊息佇列和事件迴圈

正如MDN文件所說,JavaScript 有一個基於事件迴圈的併發模型,事件迴圈負責執行程式碼、收集和處理事件以及執行佇列中的子任務。這個模型與其它語言中的模型截然不同,比如 C 和 Java。

在併發模型中,訊息佇列用於處理最早的訊息。 只要有事件發生,便會加入訊息佇列中。通過理解這些概念,你可以更好地理解JS在底層是如何工作的,以及知道你的程式碼是如果執行的。

10.時間間隔

想在 JS 有計劃的呼叫的函式,可以使用下面兩個函式:

  • setTimeout 允許我們在特定時間間隔後執行一次函式。
  • setInterval允許我們重複執行一個函式,從一個特定的時間間隔開始,然後以該間隔連續重複。

這些與前面的訊息佇列和事件處理程式的概念有些關聯。因此,通過理解時間間隔方法,我們可以理解它們是如何工作的,並在我們的用例中有效地使用它們。

11.JS 引擎

JavaScript引擎是執行 JS 程式碼的計算機程式或直譯器。JS 引擎可以用多種語言編寫。例如,驅動Chrome瀏覽器的V8引擎是用 c++ 編寫的,而驅動Firefox瀏覽器的SpiderMonkey引擎是用 C 和 c++編 寫的。

要想編寫高效的程式碼,你必須瞭解所使用的 JS 引擎。使用webview的移動開發人員要特別注意這一點。

12.按位運算

按位運算操作將值視為(0和1),而不是十進位制,十六進位制或八進位制數字。 按位運算子對此類二進位制表示形式執行其操作,但是它們返回標準JavaScript數值。

通常,很少會在程式碼中使用這些操作,但是它們確實有一些用例。 比如,可以使用它們來查詢偶數和奇數值,顏色轉換,顏色提取等等。

通過全面瞭解這些按位操作,您可以很好地使用 WebGL 之類的技術,因為它包含許多畫素操作。

13. DOM 和佈局樹

我們大多數人都聽說過文件物件模型(DOM),但只有少數人對此有深入的瞭解。 你知道在瀏覽器中看到的不是DOM嗎? 而是渲染樹,它實際上是DOM和CSSOM的組合。

通過理解DOM的工作方式、結構以及頁面的渲染方式,我們就能夠在 JS 的幫助下動態地操作web頁面。這對於確保我們的應用程式具有高標準的效能尤為必要。

14.類和工廠

JavaScript 不是一種物件導向的語言。 但是,為了模仿OOP屬性,使用了建構函式。 根據Tania的說法,“ JavaScript中的類實際上並沒有提供其他功能,只是在原型和繼承上提供語法糖,因為它們提供了更簡潔,更優雅的語法。 由於其他程式語言都使用類,因此 JS 中的類語法使開發人員在各種語言之間移動變得更加簡單。”

工廠函式是不是返回物件的類或建構函式的函式。 根據JS專家Eric Elliot的說法,“在JavaScript中,任何函式都可以返回一個新物件。 如果它不是建構函式或類,則稱為工廠函式。”

當開始開發規模更大的應用程式時,理解這兩個概念是很有必要的。

15.this 關鍵字和 apply,callbind方法

就我個人而言,我認為對於一個JS開發人員來說,理解this 關鍵字是至關重要的。如果你不能正確地理解它,將來你開發的專案也會經常遇到this相關的問題。

如果你對this關鍵字很清楚,則可以看看applycallbind方法,這些都可以解決 this 指向引發的問題。

16.建構函式和 “instanceOf” 運算子

建構函式就像常規函式一樣。 但是它們有很多差異,函式名稱以大寫字母開頭,並且只能由new運算子執行。 具有OOP開發經驗的程式設計師會熟悉new關鍵字。

為了正確識別物件的型別,我們使用instanceOf運算子。 簡單來說,它檢查一個物件是否是另一個物件的例項。

這才助於你理解物件如何相互繼承,繼承是通過原型實現的。

17.原型

這是 JS 中最令人困惑的概念之一,即使對於有十年經驗的人來說也是如此。

JavaScript中的原型是在物件之間共享通用功能的機制。 JavaScript中幾乎所有物件都是Object的例項。 物件會從Object.prototype繼承所有屬性和方法。

簡單來說,原型是 JS 物件從中繼承方法和屬性的物件。

理解了原型,你就可以構建高效,快速的應用程式。

18. 使用 newObject.createObject.assign 建立物件

建立物件有很多方法。 但是,大都會選擇Object.create方法而不是new關鍵字。這是有原因的,因為 使用Object.create方法時,可以將現有物件用作新建立的物件的原型。 這樣就可以重用現有物件的屬性和功能,有點像OOP中的繼承概念。

使用Object.assign方法時,可以將可列舉的自身屬性從一個或多個源物件複製到目標物件。 在這種情況下,目標物件的原型不包含源物件的屬性。 這是這兩種方法之間的主要區別。

通過了解物件建立的這三種方式,可以根據實際情況適當地使用它們,以建立效率更高的程式。

19.map,filter, reduce 方法

當涉及到陣列操作時,這三種方法非常有用。 它們可以在Array原型中找到。

如果你有一個陣列,並且想對每個元素做一些事情,那麼您可以使用map方法。

如果你有一個陣列,並且想通過某些條件來過濾一些值時,則可以使用filter方法。

reduce() 方法對陣列中的每個元素執行一個由你提供的reducer函式(升序執行),將其結果彙總為單個返回值。

典型的例子就是對陣列的所有元素進行求和:

let numbers = [1,2,3,4,5,6]
const reduced = numbers.reduce( (accumulator, currentValue) => accumulator + currentValue )
console.log(reduced)
// 21

請注意,上述三種方法不會更改原始陣列的值。

20.純函式,副作用和狀態變更

這三個概念對於 JS 開發人員而言非常重要,狀態變更對於使用 React 的開發人員尤其重要。

純函式指的是一個函式的返回結果只依賴於它的引數,並且在執行過程裡面沒有副作用。

函式副作用是指當呼叫函式時,除了返回函式值之外,還對主呼叫函式產生附加的影響。副作用的函式不僅僅只是返回了一個值,而且還做了其他的事情,比如:

  • 修改了一個變數
  • 直接修改資料結構
  • 設定一個物件的成員
  • 丟擲一個異常或以一個錯誤終止
  • 列印到終端或讀取使用者輸入
  • 讀取或寫入一個檔案
  • 在螢幕上畫圖

狀態變更是指你更改變數值的地方。 如果你對變數進行更改,則可能會影響到其他函式,具體取決於變數被更改之前的值。 在React環境中,建議我不要改變狀態。

21. 閉包

閉包很難理解。 但是一旦理解,你會覺得 JS 其實也挺好的。 線上上有足夠的資源。 你花足夠的時間學習閉包,掌握理解它並不難。

使用閉包可以訪問內部作用域中外部作用域的作用域。 每次建立函式時都會在函式建立時建立JavaScript閉包。

22. 高階函式

高階函式是將其他函式作為引數或返回結果的函式。 你可以建立僅負責一項任務的較小函式,然後在這些較小函式的幫助下構造複雜函式。 這也會提交程式碼的可重用性。

23.遞迴

遞迴是所有程式語言中的一個常見概念。簡單地說,遞迴就是把大問題分解成小問題,然後解決小問題一種思路。

儘管遞迴可能是一個讓你頭疼的令人困惑的概念,但是通過大量的練習,從一些小問題開始,你可以更好地理解它。

24.集合與生成器

ES6 中新引入了集合和生成器。 新引入的集合有MapSetWeakSetWeakMap。 這些集合為我們提供一些很方便的操作。 瞭解它們的方式至關重要,尤其是對於現代JavaScript。

生成器有時很難理解,特別是對於初學者。 生成器允許我們編寫程式碼函式,從而能夠暫停和重新啟動函式,而不會阻止其他程式碼的執行,這在JavaScript中是很不常見的。

25. Promise

JecelynPromises 的解釋如下:“想象一下你是個孩子。 你媽媽向你保證,她下週會買一部新手機給你。”

你要到下週才能知道你是否能屋那部手機。你的媽媽要麼真的給你買了一個全新的手機,要麼因為不開心就不給你買。

這算是一個承諾。 一個 Promise 有三個狀態,分別是:

  1. Pending:你不知道你是否會能得到那個電話
  2. Fulfilled:媽媽高興了,給你買了一部新手機
  3. Rejected:老媽不開心了,就是不給買,愛咋滴就咋滳

26.非同步程式設計

要了解什麼是非同步程式設計,首先要先積善成德什麼是同步程式設計。 同步程式設計是執行緒阻塞的,由於 JS 是單執行緒的,因此程式碼將逐行執行。

但是使用非同步程式碼,你可以執行一些比較耗時的任務。 當你必須執行花費很長時間才能完成的多個任務時,此功能特別有用。 但是在某些情況下,即使是需要執行很長時間的程式碼,也可能需要用同步的方式,這時就可以使用async/await

27. ES6 箭頭函式

箭頭函式是 ES6 的新增功能,是常規函式的語法替代。 區別在於箭頭函式不繫結到thisargumentssupernew.target關鍵字。 這使得箭頭函式在某些情況下是一個不錯的選擇,而在另一些情況下則是一個非常糟糕的選擇。

因此,不要一上來就使用箭頭函式。 需要根據你實際情況還使用它們。

大家都說簡歷沒專案寫,我就幫大家找了一個專案,還附贈【搭建教程】

28. 資料結構

無論使用哪種程式語言,資料結構都是開發人員應具備的基本知識之一。

糟糕的程式設計師擔心程式碼,好的程式設計師擔心資料結構和它們之間的關係。

資料結構方面,你應該瞭解連結串列,佇列,堆疊,樹,圖和雜湊表。

29.時間複雜度

不管程式語言如何,時間複雜度分析也是計算機程式設計的另一個基礎。 為了構建更好的應用程式,你應該編寫更好的解決方案。 為此,你需要了解時間複雜度的概念。 有時也稱為BigO

30.演算法

這也是在計算機基礎課程中首先要教的內容之一。 簡而言之,演算法是逐步實現目標的過程。 程式設計師應該能夠從演算法的角度看任何問題。

儘管有成千上萬個用例的大量演算法,但是下面兩個很常見:

  • 查詢
  • 排序

這兩個用例對程式設計師來說是非常常見的,至少應該瞭解實現它們的已知演算法。沒有固定的規則規定你應該使用這些演算法之一,但是這些演算法在效能方面是眾所周知的,並且有很好的文件證明。

你甚至可以建立自己的演算法,並將其介紹給世界。如果它比目前已知的演算法更好,你可能會成為下一個程式設計明星

31.繼承,多型和程式碼重用

JS 中的繼承可用於原型來實現。 這是因為 JS 是非OOP語言。 但是 JS 通過提供原型繼承來提供OOP的某些功能。

多型是物件、變數或函式可以採用多種形式的概念。在 JS 中,要看到多型的效果有點困難,因為在靜態型別的系統中,多型的經典型別更明顯。

以上兩個概念都可以幫助我們在 JS 中實現更好程式碼重用。

32.設計模式

設計模式(Design pattern)代表了最佳的實踐,通常被有經驗的物件導向的軟體開發人員所採用。設計模式是軟體開發人員在軟體開發過程中面臨的一般問題的解決方案。這些解決方案是眾多軟體開發人員經過相當長的一段時間的試驗和錯誤總結出來的。

33. 函數語言程式設計

函數語言程式設計是一種程式設計正規化,是一種構建計算機程式結構和元素的風格,它把計算看作是對數學函式的評估,避免了狀態的變化和資料的可變。

你需要掌握函數語言程式設計的幾個概念:

  • 純函式
  • 不可變
  • 引用透明性
  • 高階函式

34. 簡潔程式碼的原則

無論使用哪種程式語言,這都是每個開發人員都應該掌握的一項基本技能。 每種程式語言都有一套單獨的良好實踐。 儘管這些“良好”做法是主觀的,並且在工作場所之間存在差異,但有些慣例被認為是“良好”。

通過遵循這些程式碼原則,可以確保每個人都可以閱讀和維護你的程式碼。 這也會幫助你和你的團隊在應用程式開發過程中順利合作。

35. 解構賦值

在ES6中引入瞭解構賦值操作符,它非常有用。對於相同的用例,它們比以前的實現更簡單、更有效。

36. ES2020新特性

程式設計的優點之一是,如果你不去不斷學習,你永遠不會成為該領域專家。 程式語言會隨著時間不斷髮展,因為每個主要版本中都引入了其他新的功能。

這也說明了你對某個概念的專業知識很可能在將來的10年後會過期,因為會有更好的替代版本與版本更新一起釋出。 對於任何程式語言,這都是非常常見的情況。

ES202 0釋出了幾個新特性,包括可選連結、空值合併、動態匯入等等。你必須學習這些新概念,以跟上快速變化的It世界。

掌握一門語言需要多年的經驗和時間,但是知道要掌握什麼會讓事情變得更容易,希望這 36 個概念能對你有所幫助。

人才們的 【三連】 就是小智不斷分享的最大動力,如果本篇部落格有任何錯誤和建議,歡迎人才們留言,最後,謝謝大家的觀看。


程式碼部署後可能存在的BUG沒法實時知道,事後為了解決這些BUG,花了大量的時間進行log 除錯,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug

交流

有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。

本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。

相關文章