JavaScript 原語

在JavaScript,一個原語(primitive–原語值,原語數據類型)是一個數據,不是一個對象並且沒有方法。有七種原語數據類型:

  • string
  • number
  • bigint
  • boolean
  • null
  • undefined
  • symbol

一般,原語表現爲語言實現的最底層。

所有的原語是不可改變的immutable)。這裏面不要混淆一個原語本身和一個被分配類原語值的變量。一個變量可以重新分配一個值,但是這個存在的值不能使用objectsarraysfunctions改變。


Example

這個例子幫你理解原語值是不可改變的。

// 使用一個字符串方法不能改變一個字符串
var bar = "baz";
console.log(bar); // bar
bar.toUpperCase();
console.log(bar) // bar

// 使用數組方法改變數組
var foo = [];
console.log(foo);  // []
foo.push('plugh');
console.log(foo)  // ['plugh']

// 賦值給原語一個新(不可改變的)值
bar = bar.toUpperCase()  // BAZ

一個原語能夠被替換,但不能直接改變。


另一個例子[遞進]

以下的例子將幫助你理解JavaScript如何處理原語。

// 原語
let foo = 5;

// 定義一個函數改變原語值
function addTwo(num) {
	num += 2;
}

// 定義另一個函數做同樣的事情
function addTwo_V2(foo) {
	foo += 2;
}

// 傳遞我們的原語作爲參數調用第一個函數
addTwo(foo);
// 得到當前的原始值
console.log(foo);  // 5

// 調用第二個函數
addTwo_v2(foo);
console.log(foo); // 5

你認爲它會用7代替5嗎?如果是這樣,讀這段代碼如何運行:

  • 對於addTwoaddTwo_v2函數調用,JavaScript查找foo的值。它能夠找到我們第一個實例化的變量。
  • 找到之後,表達式被計算,foo被5替換並且JavaScript引擎傳遞值給函數作爲參數。
  • 在函數體執行這個聲明之前,JavaScript獲取原始參數的副本並且創建一個本地副本。這些副本,僅僅存在函數的作用域之內,是可以通過我們函數定義的標識符訪問的(num之於addTwofoo之於addTwo_v2
  • 然後,函數的聲明被執行:
    • 在第一個函數,一個本地的num變量已經被創建。我們將他的值加2,而不是改變原始的foo的值!
    • 在第二個函數,一個本地的foo變量已經被創建。同樣我們把它加2,而不是原始的(外部的)foo的值!另外,在這種情況下,外部的foo值不能被直接訪問。這是因爲JavaScript的詞法作用域和由此產生的變量陰影。本地的foo隱藏了外部的foo。對於更多信息,看閉包。(注意:window.foo仍然可以訪問外部的foo變量)。
  • 總結,任何內部的改變都不會影響原始的foo,是由於我們使用了它的副本。

這就是爲什麼原語是不變的— 相反,我們使用了一個副本來代替它,原始值並不受影響。


JavaScript中的原語封裝對象

除了nullundefined,所有的原語值都有等價的封裝對象值:

  • String對應string原語
  • Number對應number原語
  • BigInt對應bigint原語
  • Boolean對應boolean原語
  • Symbol對應symbol原語

封裝器的valueOf()返回原語的值。


參考:Primitive

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章