在 JavaScript 中,我們能為原始型別新增一個屬性或方法嗎?

技術漫談發表於2020-11-17

原始型別的方法

JavaScript 允許我們像使用物件一樣使用原始型別(字串,數字等)。JavaScript 還提供了這樣的呼叫方法。我們很快就會學習它們,但是首先我們將瞭解它的工作原理,畢竟原始型別不是物件(在這裡我們會分析地更加清楚)。

我們來看看原始型別和物件之間的關鍵區別。

一個原始值:

  • 是原始型別中的一種值。
  • 在 JavaScript 中有 7 種原始型別:stringnumberbigintbooleansymbolnullundefined

一個物件:

  • 能夠儲存多個值作為屬性。
  • 可以使用大括號 {} 建立物件,例如:{name: "John", age: 30}。JavaScript 中還有其他種類的物件,例如函式就是物件。

關於物件的最好的事兒之一是,我們可以把一個函式作為物件的屬性儲存到物件中。

let john = {
  name: "John",
  sayHi: function() {
    alert("Hi buddy!");
  }
};

john.sayHi(); // Hi buddy!

所以我們在這裡建立了一個包含 sayHi 方法的物件 john

許多內建物件已經存在,例如那些處理日期、錯誤、HTML 元素等的內建物件。它們具有不同的屬性和方法。

但是,這些特性(feature)都是有成本的!

物件比原始型別“更重”。它們需要額外的資源來支援運作。

當作物件的原始型別

以下是 JavaScript 建立者面臨的悖論:

  • 人們可能想對諸如字串或數字之類的原始型別執行很多操作。最好將它們作為方法來訪問。
  • 原始型別必須儘可能的簡單輕量。

而解決方案看起來多少有點尷尬,如下:

  1. 原始型別仍然是原始的。與預期相同,提供單個值
  2. JavaScript 允許訪問字串,數字,布林值和 symbol 的方法和屬性。
  3. 為了使它們起作用,建立了提供額外功能的特殊“物件包裝器”,使用後即被銷燬。

“物件包裝器”對於每種原始型別都是不同的,它們被稱為 StringNumberBooleanSymbol。因此,它們提供了不同的方法。

例如,字串方法 str.toUpperCase() 返回一個大寫化處理的字串。

用法演示如下:

let str = "Hello";

alert( str.toUpperCase() ); // HELLO

很簡單,對吧?以下是 str.toUpperCase() 中實際發生的情況:

  1. 字串 str 是一個原始值。因此,在訪問其屬性時,會建立一個包含字串字面值的特殊物件,並且具有有用的方法,例如 toUpperCase()
  2. 該方法執行並返回一個新的字串(由 alert 顯示)。
  3. 特殊物件被銷燬,只留下原始值 str

所以原始型別可以提供方法,但它們依然是輕量級的。

JavaScript 引擎高度優化了這個過程。它甚至可能跳過建立額外的物件。但是它仍然必須遵守規範,並且表現得好像它建立了一樣。

數字有其自己的方法,例如,toFixed(n) 將數字舍入到給定的精度:

let n = 1.23456;

alert( n.toFixed(2) ); // 1.23

我們將在後面 Number 型別字串 章節中看到更多具體的方法。

構造器 String/Number/Boolean 僅供內部使用

像 Java 這樣的一些語言允許我們使用 new Number(1)new Boolean(false) 等語法,明確地為原始型別建立“物件包裝器”。

在 JavaScript 中,由於歷史原因,這也是可以的,但極其 不推薦。因為這樣會出問題。

例如:

alert( typeof 0 ); // "number"

alert( typeof new Number(0) ); // "object"!

物件在 if 中始終為真,因此此處的 alert 將顯示:

let zero = new Number(0);

if (zero) { // zero 為 true,因為它是一個物件
  alert( "zero is truthy?!?" );
}

另一方面,呼叫不帶 new(關鍵字)的 String/Number/Boolean 函式是完全理智和有用的。它們將一個值轉換為相應的型別:轉成字串、數字或布林值(原始型別)。

例如,下面完全是有效的:

let num = Number("123"); // 將字串轉成數字

null/undefined 沒有任何方法

特殊的原始型別 nullundefined 是例外。它們沒有對應的“物件包裝器”,也沒有提供任何方法。從某種意義上說,它們是“最原始的”。

嘗試訪問這種值的屬性會導致錯誤:

alert(null.test); // error

總結

  • nullundefined 以外的原始型別都提供了許多有用的方法。我們後面的章節中學習這些內容。
  • 從形式上講,這些方法通過臨時物件工作,但 JavaScript 引擎可以很好地調整,以在內部對其進行優化,因此呼叫它們並不需要太高的成本。

作業題

先自己做題目再看答案。

我能為字串新增一個屬性嗎?

重要程度:⭐️⭐️⭐️⭐️⭐️

思考下面的程式碼:

let str = "Hello";

str.test = 5;

alert(str.test);

你怎麼想的呢,它會工作嗎?會得到什麼樣的結果?

答案:

在微信公眾號「技術漫談」後臺回覆 10501 獲取作業答案。


現代 JavaScript 教程:開源的現代 JavaScript 從入門到進階的優質教程。React 官方文件推薦,與 MDN 並列的 JavaScript 學習教程

線上免費閱讀:https://zh.javascript.info


微信掃描下方二維碼,關注公眾號「技術漫談」,訂閱更多精彩內容。

相關文章