33 個 JavaScript 核心概念系列(一): 資料型別

路某人發表於2019-01-05

33 個 JavaScript 核心概念系列(一): 資料型別

一、定義

1. 什麼是資料型別?

資料型別,就是將資料按照某一規則進行區別時所定義的分類標籤。比如說,同樣都是漢字組成的詞語,要分動詞、名詞、介詞等。

2. 為什麼會有資料型別?它出現的意義是什麼?

對資料分類,主要有兩個原因:

第一,為了限制不同種類資料的操作。比如說當你宣告一個變數是一個數字,那麼,就只能對這個變數進行數字能進行的操作,這在編譯程式碼及排查錯誤時尤為重要。

第二,由於所有的資料都要儲存在計算機中,不同型別資料的儲存位置及所需要的記憶體大小也不一樣,而對資料分類後,程式設計時需要用大資料的時候才需要申請大記憶體,這樣可以充分利用記憶體。

例如大胖子必須睡雙人床,就給他雙人床,瘦的人單人床就夠了。

二、JavaScript 中的資料型別

1. 為什麼稱 JavaScript 為弱型別語言?

JavaScript 中變數是沒有型別的,只有值才有。變數可以隨時持有任何型別的值。

舉個例子:

// js
let a = 4;
a = '4';
a = false;
複製程式碼

從上面的例子中可以看到,我們宣告 a 是一個數字,但是我們在之後將 a 的值又改成了字串和布林值(後面會講這些型別)。可以看到,變數 a 的型別是可以隨意轉變的,這在強型別語言裡是不允許的。

因此,判斷一門語言是強型別還是弱型別,就看這門語言中一個變數是否可以賦不同資料型別的值。

2. JavaScript 有哪些資料型別?

在 JavaScript 中,共有七種資料型別,其中,六種是基本/原始型別,一種是物件/複合/引用型別。

基本型別:

  • 字串(String):表示一個字串,如“find”。
  • 數字(Number):表示一個數字,如 45 。
  • 布林(Boolean):布林值,包括 false 和 true 。
  • 未定義(undefined):只有一個值,undefined , 表示未給變數賦值。
  • 空值(null):只有一個值, null , 表示空值得關鍵字。
  • Symbol(es6新增):表示一個唯一且不可改變的值。

引用型別:

  • 物件(object): 各種值組成的集合。

其中,物件型別還有一些子型別,如陣列,函式,JavaScript 的內建函式等。

3. 基本資料型別和複合資料型別有什麼區別?

主要有兩點:

  1. 基本型別的資料是不可再拆分的。 這也就是為什麼稱他為基本型別,就像組成單詞的 26 個英文字母、組成數字的 0 -9;而複合型別的資料,是由基本型別組成。比如一個單詞,可以由數個字母組成,一個句子,可以由數字、字母及標點複合組成。

  2. 它們在計算機中的儲存方式不同。計算機儲存資料時為了記憶體及執行速度考慮,往往會對儲存做優化,有的會將值本身儲存在棧記憶體中,也有可能會在棧記憶體中儲存一個值的引用,而把值本身存在堆記憶體中。對於不同的語言,實現起來或許會有不一致,但思想都是如此。

4. js 中值型別和引用型別的儲存方式是怎樣的?

對於 js 來講,是沒有棧記憶體的概念的,但是 js 在編譯執行程式碼時,會首先進入一個執行上下文,在執行上下文的建立階段,會開闢一片區域,用來儲存變數和它們的值,這個區域就叫做變數物件。

大概長這個樣子:

33 個 JavaScript 核心概念系列(一): 資料型別

如上圖所示,對於基本型別的變數,他們的變數名和值都會儲存在這個變數物件中,而對於 d ,這個引用型別的值,則只是將這個變數的名字和地址存在變數物件中,變數的值是儲存在堆記憶體空間的。

關於執行上下文,後面會有文章專門講,暫時先不做深入講解。

5. 如何判斷一個資料的資料型別?

- typeof 方法

對於一個變數,使用 typeof 方法會返回一個唯一的資料型別字串。但這個方法並不怎麼靠譜。

型別 typeof 值
23 number "number"
"abc" string "string"
false boolean "boolean"
undefined undefined "undefined"
Symbol() symbol "symbol"
{} object "object"
null null "object"
function(){} object "funciton"

從上表中我們看到,有兩處地方和我們預期不一致。

  1. typeof null 返回的是 "object" 而不是 "null"。這是 js 語言設計時的一個 bug, 並且在未來也不會更改。

    想要正確判斷 null 可以加一個條件:

    function typeOf(a) {
        if(!a && typeof a === "object") return "null";
        return typeof a;
    }
    typeOf({}); // "object"
    typeOf(null); // "null"
    複製程式碼
  2. typeof function(){} === "function", 這是因為function 作為 js 的一等公民,是可以呼叫的物件,設計者認為有必要將它和普通物件區別開來。

- Object.prototype.toString.call() 方法

除了 typeof 方法外,呼叫 Object.prototype.toString.call() 方法 也可以返回一個包含資料型別的字串,並且更為準確。

型別 Object.prototype.toString.call(值)
23 number '[object Number]'
"abc" string '[object String]'
false boolean '[object Boolean]'
undefined undefined '[object Undefined]'
Symbol() symbol '[object Symbol]'
{} object '[object Object]'
null null '[object Null]'
function(){} object '[object Function]'
[] object '[object Array]'

從上面們可以看出,這方法對於型別的檢測更加精確。

因此,我們可以寫一個函式,用來精確檢測型別。

function getClass (a) {
  const str = Object.prototype.toString.call(a)
  return /^\[object (.*)\]$/.exec(str)[1]
}
getClass(null) // "Null";
...
複製程式碼

原文地址: 落明的 blog

相關文章