JS數據類型(1):數據類型與內存空間

數據類型是 JavaScript 中最基礎的知識點,咱們在平常的開發中,無時無刻不在用到數據類型相關的知識。在面試中,數據類型也是最基礎的考點,本文將會以幾道常見的面試題開頭,依次解釋其中須要咱們掌握的知識點。git

關於數據類型與數據存放相關的面試題:github

  1. JavaScript 中變量類型分爲幾種,區別是什麼?
  2. 基本數據類型和引用數據類型的區別?
  3. 不一樣數據類型分別存放在哪裏?
  4. 棧和堆的區別是什麼?分別怎麼存儲數據?
  5. 代碼題。結果以及爲何?
var a = { age: 19 };
var b = a;
a = null;
console.log(b); // ?
複製代碼
  1. const 定義的值能修改麼?
const obj = {
  name: 'zs',
  age: 20
};

obj.age = 30;
console.log(obj); // ?
複製代碼

這些問題都比較基礎,可是若是你還有模棱兩個的地方,不妨再仔細閱讀一下下面的內容。面試

一. 數據類型

衆所周知,JavaScript 中有 7 種數據類型,分別是:Undefined、Null、Boolean、Number、String、Symbol 以及 Object。微信

其中,前 6 種咱們稱之爲基本數據類型,最後一種咱們稱之爲引用數據類型ui

另外一方面,在 JavaScript 中,一個變量能夠隨時持有任何類型的值。好比:spa

var a = '3';
a = 50;
複製代碼

這代表:JavaScript 中的變量是沒有類型的,只有值纔有。3d

二. 棧、堆以及數據存放

簡單來講,在 JavaScript 中,每個數據都須要有它所對應的內存空間。而內存空間主要分爲兩種:棧內存(Stack)堆內存(Heap)code

棧內存通常用來存放基本數據類型的值(Undefined、Null、Boolean、Number、String、Symbol)。棧內存由系統自動分配內存空間,存儲值的大小固定,空間小,運行效率更高。cdn

堆內存用來存放引用數據類型的值(對象)。當咱們聲明瞭一個引用類型的值(對象)以後,這個引用類型的值(對象)保存在堆內存中。另外一方面,這個值(對象)的地址會被保存在棧內存中,用來引用這個對象。同時,堆內存存儲的值大小不定,能夠動態調整,空間大,運行效率更低。對象

爲了形象的說明,咱們把下面的例子用圖來表示一下:

var c = { name: 'zs' }; // 引用數據類型
var b = 'abc'; // 基本數據類型
var a = 10; // 基本數據類型
複製代碼

經過上面的解釋以及圖示,咱們能夠知道:

1. 基本數據類型是按值訪問的,能夠操做保存在變量中實際的值。

2. 引用數據類型是按引用訪問的。

三. 賦值與傳遞

由於保存基本數據類型和引用數據類型的方式不一樣,因此從一個變量向另外一個變量複製基本數據類型值和引用數據類型值時,也存在不一樣。

對於基本數據類型的值而言,咱們老是經過值複製的方式來賦值和傳遞。

var num1 = 10;
var num2 = num1;
num1 = 30;
console.log(num2); // 10
複製代碼

在這個例子中,10 是一個 Number 類型的值,變量 num1 持有該值的一個副本。當咱們將 num1 的值賦值給 num2 時,其實是新開闢了一塊內存空間,此時 num2 也持有該值的一個副本。這兩個變量的任何操做,都不會互相影響。

而對於引用數據類型而言,咱們老是經過引用複製的方式來賦值和傳遞。咱們用文章開頭的代碼題來舉例:

var a = { age: 19 };
var b = a;
a = null;
console.log(b);
複製代碼

由於變量 a 保存的是一個引用類型的值(對象),因此當把變量 a 的值賦值給變量 b 時,其實是複製了 a 引用(也就是指向堆內存的地址),此時 ab 指向同一塊內存空間。當代碼執行 a = null 時,其實是將清除了這個引用,變量 b 的指向不會發生變換。因此打印 b 的結果依舊是 { age: 19 }

這裏咱們須要明確如下兩點:

1. ab 僅僅是指向 { age: 19 },而並不是持有。

2. 引用指向的是值自己而非變量,因此一個引用沒法更改另外一個引用的指向。

四. const 定義一個常量,能夠修改麼?

咱們知道,const 聲明一個只讀常量。一旦聲明,變量的值不能修改。但看到下面的例子,是否會有一絲疑惑?

const obj = {
  name: 'zs',
  age: 20
};

obj.age = 30;
console.log(obj); // { name: 'zs', age: 30 };
複製代碼

咱們發現,代碼並無報錯。其實這個緣由也很簡單,就像上面畫的那張圖同樣,變量 obj 其實保存的是一個引用,也就是一個地址,當咱們修改對象內部的值時,變量保存的地址並無發生變化,因此是不會報錯的。

若是咱們修改代碼爲:

obj = null;
複製代碼

此時,const 聲明的變量中保存的地址就會發生變化,因此纔會報錯。

五. 總結

本文主要介紹了 JavaScript 中最基礎的概念數據類型,區分了基本數據類型與引用數據類型以及它們存放方式上的差別。正是由於這些差別,因此它們在賦值和傳遞上也有不一樣的特色。

最後,咱們拋出兩個問題:

  1. 爲何一個基本類型的值,能夠像對象同樣訪問屬性和方法?好比:
const a = '123';
a.length; // 3
複製代碼
  1. 既然基本數據類型能夠訪問屬性和方法,爲何 1.toString() 會報錯?不是應該變爲 "1" 麼?

下期,咱們來聊聊數據類型中的封裝對象。

以上內容,若有錯誤,歡迎指正。

文章會在 Github ,以及微信公衆號(野蠻成長實驗室)首發,歡迎關注和 Star。

相關文章
相關標籤/搜索