在 JavaScript 中,我們能為原始型別新增一個屬性或方法嗎?
阿新 • • 發佈:2020-11-17
![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/18d583c0d4084119a03ba18e1e8b99a6~tplv-k3u1fbpfcp-zoom-1.image)
# 原始型別的方法
JavaScript 允許我們像使用物件一樣使用原始型別(字串,數字等)。JavaScript 還提供了這樣的呼叫方法。我們很快就會學習它們,但是首先我們將瞭解它的工作原理,畢竟原始型別不是物件(在這裡我們會分析地更加清楚)。
我們來看看原始型別和物件之間的關鍵區別。
一個原始值:
- 是原始型別中的一種值。
- 在 JavaScript 中有 7 種原始型別:`string`,`number`,`bigint`,`boolean`,`symbol`,`null` 和 `undefined`。
一個物件:
- 能夠儲存多個值作為屬性。
- 可以使用大括號 `{}` 建立物件,例如:`{name: "John", age: 30}`。JavaScript 中還有其他種類的物件,例如函式就是物件。
關於物件的最好的事兒之一是,我們可以把一個函式作為物件的屬性儲存到物件中。
```js
let john = {
name: "John",
sayHi: function() {
alert("Hi buddy!");
}
};
john.sayHi(); // Hi buddy!
```
所以我們在這裡建立了一個包含 `sayHi` 方法的物件 `john`。
許多內建物件已經存在,例如那些處理日期、錯誤、HTML 元素等的內建物件。它們具有不同的屬性和方法。
但是,這些特性(feature)都是有成本的!
物件比原始型別“更重”。它們需要額外的資源來支援運作。
## 當作物件的原始型別
以下是 JavaScript 建立者面臨的悖論:
- 人們可能想對諸如字串或數字之類的原始型別執行很多操作。最好將它們作為方法來訪問。
- 原始型別必須儘可能的簡單輕量。
而解決方案看起來多少有點尷尬,如下:
1. 原始型別仍然是原始的。與預期相同,提供單個值
2. JavaScript 允許訪問字串,數字,布林值和 symbol 的方法和屬性。
3. 為了使它們起作用,建立了提供額外功能的特殊“物件包裝器”,使用後即被銷燬。
“物件包裝器”對於每種原始型別都是不同的,它們被稱為 `String`、`Number`、`Boolean` 和 `Symbol`。因此,它們提供了不同的方法。
例如,字串方法 [str.toUpperCase()](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase) 返回一個大寫化處理的字串。
用法演示如下:
```js
let str = "Hello";
alert( str.toUpperCase() ); // HELLO
```
很簡單,對吧?以下是 `str.toUpperCase()` 中實際發生的情況:
1. 字串 `str` 是一個原始值。因此,在訪問其屬性時,會建立一個包含字串字面值的特殊物件,並且具有有用的方法,例如 `toUpperCase()`。
2. 該方法執行並返回一個新的字串(由 `alert` 顯示)。
3. 特殊物件被銷燬,只留下原始值 `str`。
所以原始型別可以提供方法,但它們依然是輕量級的。
JavaScript 引擎高度優化了這個過程。它甚至可能跳過建立額外的物件。但是它仍然必須遵守規範,並且表現得好像它建立了一樣。
數字有其自己的方法,例如,[toFixed(n)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) 將數字舍入到給定的精度:
```js
let n = 1.23456;
alert( n.toFixed(2) ); // 1.23
```
我們將在後面 [Number 型別](https://zh.javascript.info/number) 和 [字串](https://zh.javascript.info/string) 章節中看到更多具體的方法。
### 構造器 String/Number/Boolean 僅供內部使用
像 Java 這樣的一些語言允許我們使用 `new Number(1)` 或 `new Boolean(false)` 等語法,明確地為原始型別建立“物件包裝器”。
在 JavaScript 中,由於歷史原因,這也是可以的,但極其 **不推薦**。因為這樣會出問題。
例如:
```js
alert( typeof 0 ); // "number"
alert( typeof new Number(0) ); // "object"!
```
物件在 `if` 中始終為真,因此此處的 alert 將顯示:
```js
let zero = new Number(0);
if (zero) { // zero 為 true,因為它是一個物件
alert( "zero is truthy?!?" );
}
```
另一方面,呼叫不帶 `new`(關鍵字)的 `String/Number/Boolean` 函式是完全理智和有用的。它們將一個值轉換為相應的型別:轉成字串、數字或布林值(原始型別)。
例如,下面完全是有效的:
```js
let num = Number("123"); // 將字串轉成數字
```
### null/undefined 沒有任何方法
特殊的原始型別 `null` 和 `undefined` 是例外。它們沒有對應的“物件包裝器”,也沒有提供任何方法。從某種意義上說,它們是“最原始的”。
嘗試訪問這種值的屬性會導致錯誤:
```js
alert(null.test); // error
```
## 總結
- 除 `null` 和 `undefined` 以外的原始型別都提供了許多有用的方法。我們後面的章節中學習這些內容。
- 從形式上講,這些方法通過臨時物件工作,但 JavaScript 引擎可以很好地調整,以在內部對其進行優化,因此呼叫它們並不需要太高的成本。
## 作業題
先自己做題目再看答案。
### 我能為字串新增一個屬性嗎?
> 重要程度:⭐️⭐️⭐️⭐️⭐️
思考下面的程式碼:
```js
let str = "Hello";
str.test = 5;
alert(str.test);
```
你怎麼想的呢,它會工作嗎?會得到什麼樣的結果?
## 答案:
在微信公眾號「技術漫談」後臺回覆 **`10501`** 獲取作業答案。
---
> 現代 JavaScript 教程:開源的現代 JavaScript 從入門到進階的優質教程。[React 官方文件推薦,與 MDN 並列的 JavaScript 學習教程](https://zh-hans.reactjs.org/docs/getting-started.html#javascript-resources)。
>
> 線上免費閱讀:https://zh.javascript.info
---
**微信掃描下方二維碼,關注公眾號「技術漫談」,訂閱更多精彩內容。**
![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6d62b21deb3b47f7bd7c610d3c658da2~tplv-k3u1fbpfcp-zoom-1