首頁 > web前端 > js教程 > 解碼每個開發人員都應該知道 JavaScript 奇怪的部分

解碼每個開發人員都應該知道 JavaScript 奇怪的部分

Barbara Streisand
發布: 2025-01-03 02:06:38
原創
448 人瀏覽過

Decoding the Weird Parts of JavaScript Every Developer Should Know

JavaScript,我們喜愛(或又愛又恨)的語言,充滿了獨特的行為和怪癖,使其既強大又令人困惑。雖然這些「奇怪的部分」可能會讓初學者感到困惑,但掌握它們對於成為熟練的開發人員至關重要。讓我們深入研究每個開發人員都應該知道的一些令人著迷的 JavaScript 怪異之處。


1. 強迫轉換:JavaScript 的秘密魔術師

JavaScript 試圖透過在類型之間轉換值來提供幫助,但這種「幫助」可能會導致令人驚訝的結果。

例:意外的數學

console.log('5' - 3);  // 2
console.log('5' + 3);  // '53'
登入後複製
登入後複製
  • 減法:JavaScript 在減法之前將「5」轉換為數字。
  • 加法:當涉及字串時,JavaScript 會進行連接而不是相加。

為什麼它很重要

  • 如果您不小心,這種隱式轉換(類型強制)可能會引入錯誤。
  • 一律使用 Number()、String() 或 Boolean() 進行明確轉換以避免意外。

2. 這其中的奧秘

this 在 JavaScript 中的行為經常令人困惑,因為它的變化取決於如何呼叫函數。

範例:不同的上下文

function showThis() {
  console.log(this);
}

showThis();  // Window or undefined in strict mode

const obj = { method: showThis };
obj.method();  // obj

const boundFunc = showThis.bind(obj);
boundFunc();  // obj
登入後複製
登入後複製

為什麼它很重要

  • 聲明時未設定;這取決於呼叫網站。
  • 箭頭函數沒有自己的 this,這使得它們非常適合保留詞彙上下文。

3. 事件循環:非同步 JavaScript 揭秘

JavaScript 是單執行緒的,但可以透過事件循環處理非同步任務。

範例:什麼先運行?

console.log('Start');

setTimeout(() => console.log('Timeout'), 0);

Promise.resolve().then(() => console.log('Promise'));

console.log('End');
登入後複製
登入後複製

輸出

Start
End
Promise
Timeout
登入後複製
登入後複製
  • 同步程式碼先運行。
  • Promise(微任務)優先於 setTimeout(巨集任務)。

為什麼它很重要

理解事件循環是編寫高效能非同步程式碼的關鍵。


4. 閉包:記住的函數

閉包是指即使在外部函數傳回後,函數也會「記住」其詞法作用域。

範例:私有變數

function counter() {
  let count = 0;
  return function () {
    count++;
    console.log(count);
  };
}

const increment = counter();
increment();  // 1
increment();  // 2
登入後複製
登入後複製

為什麼它很重要

閉包可讓您建立私有變數並在函數呼叫之間維護狀態。


5. 原型:JavaScript 的支柱

JavaScript 使用基於原型的繼承,這表示物件可以從其他物件繼承屬性和方法。

範例:自訂方法

console.log('5' - 3);  // 2
console.log('5' + 3);  // '53'
登入後複製
登入後複製

為什麼它很重要

原型使您能夠有效地跨實例共享方法。


6. 相等性檢查:== 與 ===

JavaScript 提供鬆散相等 (==) 和嚴格相等 (===),它們的行為不同。

範例:Null 與未定義的奇怪情況

function showThis() {
  console.log(this);
}

showThis();  // Window or undefined in strict mode

const obj = { method: showThis };
obj.method();  // obj

const boundFunc = showThis.bind(obj);
boundFunc();  // obj
登入後複製
登入後複製
  • == 執行類型轉換,因此 null 大致等於 undefined。
  • === 檢查類型和值是否相等。

為什麼它很重要

除非明確需要型別轉換,否則一律使用 ===。
避免直接比較非原始值 ({} !== {})。


7. 不變性和引用型

JavaScript 將物件和陣列視為參考類型,這表示對引用的變更會影響原始參考。

範例:複製陷阱

console.log('Start');

setTimeout(() => console.log('Timeout'), 0);

Promise.resolve().then(() => console.log('Promise'));

console.log('End');
登入後複製
登入後複製

為什麼它很重要

  • 使用 Object.assign() 或展開運算子 ({ ...original }) 建立淺拷貝。
  • 對於深度複製,請考慮 Lodash 或 StructuredClone 等函式庫。

8. NaN:並不像看起來那麼簡單

NaN 代表“不是數字”,但它的行為一點也不簡單。

範例:比較 NaN

Start
End
Promise
Timeout
登入後複製
登入後複製

為什麼它很重要

當您需要對 NaN 等特殊情況進行嚴格等效時,請使用 Object.is。


9. 吊裝:首先聲明什麼?

提升將變數和函數宣告移到其作用域的頂端。

範例:提升變數

function counter() {
  let count = 0;
  return function () {
    count++;
    console.log(count);
  };
}

const increment = counter();
increment();  // 1
increment();  // 2
登入後複製
登入後複製
  • var 宣告被提升但初始化為未定義。
  • 函數宣告全面提升。

為什麼它很重要

使用 let 和 const 來避免變數提升混亂。


10. 奇怪的預設值:預設參數

預設參數使函數更加靈活,但與 undefined 結合使用時可能會表現得很奇怪。

範例:預設值與參數

function Person(name) {
  this.name = name;
}

Person.prototype.greet = function () {
  console.log(`Hello, my name is ${this.name}`);
};

const alice = new Person('Alice');
alice.greet();  // Hello, my name is Alice
登入後複製

為什麼它很重要

僅當參數未定義而非 null 時才套用預設參數。


結論:擁抱怪異

JavaScript 的怪癖讓它既令人沮喪又有趣。了解這些行為不僅能讓您成為更好的開發人員,還能幫助您欣賞語言的靈活性和設計選擇。

您遇過哪些怪癖,您是如何解決的?在下面的評論中分享你的想法!

以上是解碼每個開發人員都應該知道 JavaScript 奇怪的部分的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板