Javascript 原始類型的方法

2023-02-17 10:44 更新

JavaScript 允許我們像使用對象一樣使用原始類型(字符串,數(shù)字等)。JavaScript 還提供了這樣的調(diào)用方法。我們很快就會學習它們,但是首先我們將了解它的工作原理,畢竟原始類型不是對象(在這里我們會分析地更加清楚)。

我們來看看原始類型和對象之間的關(guān)鍵區(qū)別。

一個原始值:

  • 是原始類型中的一種值。
  • 在 JavaScript 中有 7 種原始類型:?string?,?number?,?bigint?,?boolean?,?symbol?,?null ?和 ?undefined?。

一個對象:

  • 能夠存儲多個值作為屬性。
  • 可以使用大括號 ?{}? 創(chuàng)建對象,例如:?{name: "John", age: 30}?。JavaScript 中還有其他種類的對象,例如函數(shù)就是對象。

關(guān)于對象的最好的事兒之一是,我們可以把一個函數(shù)作為對象的屬性存儲到對象中。

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

john.sayHi(); // Hi buddy!

所以我們在這里創(chuàng)建了一個包含 sayHi 方法的對象 john。

許多內(nèi)建對象已經(jīng)存在,例如那些處理日期、錯誤、HTML 元素等的內(nèi)建對象。它們具有不同的屬性和方法。

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

對象比原始類型“更重”。它們需要額外的資源來支持運作。

當作對象的原始類型

以下是 JavaScript 創(chuàng)建者面臨的悖論:

  • 人們可能想對諸如字符串或數(shù)字之類的原始類型執(zhí)行很多操作。最好使用方法來訪問它們。
  • 原始類型必須盡可能的簡單輕量。

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

  1. 原始類型仍然是原始的。與預期相同,提供單個值
  2. JavaScript 允許訪問字符串,數(shù)字,布爾值和 symbol 的方法和屬性。
  3. 為了使它們起作用,創(chuàng)建了提供額外功能的特殊“對象包裝器”,使用后即被銷毀。

“對象包裝器”對于每種原始類型都是不同的,它們被稱為 String、Number、Boolean、Symbol 和 BigInt。因此,它們提供了不同的方法。

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

用法演示如下:

let str = "Hello";

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

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

  1. 字符串 ?str ?是一個原始值。因此,在訪問其屬性時,會創(chuàng)建一個包含字符串字面值的特殊對象,并且具有可用的方法,例如 ?toUpperCase()?。
  2. 該方法運行并返回一個新的字符串(由 ?alert ?顯示)。
  3. 特殊對象被銷毀,只留下原始值 ?str?。

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

JavaScript 引擎高度優(yōu)化了這個過程。它甚至可能跳過創(chuàng)建額外的對象。但是它仍然必須遵守規(guī)范,并且表現(xiàn)得好像它創(chuàng)建了一樣。

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

let n = 1.23456;

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

我們將在后面 數(shù)字類型 和 字符串 章節(jié)中看到更多具體的方法。

構(gòu)造器 ?String/Number/Boolean? 僅供內(nèi)部使用

像 Java 這樣的一些語言允許我們使用 new Number(1) 或 new Boolean(false) 等語法,明確地為原始類型創(chuàng)建“對象包裝器”。

在 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?!?" );
}

另一方面,調(diào)用不帶 new(關(guān)鍵字)的 String/Number/Boolean 函數(shù)是可以的且有效的。它們將一個值轉(zhuǎn)換為相應的類型:轉(zhuǎn)成字符串、數(shù)字或布爾值(原始類型)。

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

let num = Number("123"); // 將字符串轉(zhuǎn)成數(shù)字

null/undefined 沒有任何方法

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

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

alert(null.test); // error

總結(jié)

  • 除 ?null ?和 ?undefined ?以外的原始類型都提供了許多有用的方法。我們后面的章節(jié)中學習這些內(nèi)容。
  • 從形式上講,這些方法通過臨時對象工作,但 JavaScript 引擎可以很好地調(diào)整,以在內(nèi)部對其進行優(yōu)化,因此調(diào)用它們并不需要太高的成本。

任務(wù)


我能為字符串添加一個屬性嗎?

重要程度: 5

思考下面的代碼:

let str = "Hello";

str.test = 5;

alert(str.test);

你怎么想的呢,它會工作嗎?會得到什么樣的結(jié)果?


解決方案

試試運行一下:

let str = "Hello";

str.test = 5; // (*)

alert(str.test);

根據(jù)你是否開啟了嚴格模式 use strict,會得到如下結(jié)果:

  1. ?undefined?(非嚴格模式)
  2. 報錯(嚴格模式)。

為什么?讓我們看看在 (*) 那一行到底發(fā)生了什么:

  1. 當訪問 ?str ?的屬性時,一個“對象包裝器”被創(chuàng)建了。
  2. 在嚴格模式下,向其寫入內(nèi)容會報錯。
  3. 否則,將繼續(xù)執(zhí)行帶有屬性的操作,該對象將獲得 ?test ?屬性,但是此后,“對象包裝器”將消失,因此在最后一行,?str ?并沒有該屬性的蹤跡。

這個例子清楚地表明,原始類型不是對象。

它們不能存儲額外的數(shù)據(jù)。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號