天天看點

JavaScript之基本資料類型和引用資料類型的差別

基本資料類型和引用資料類型

1. 基本資料類型

ES5裡面有五大基本資料類型:string、number、boolean、undefined、null

ES6裡面又新增了一個基本資料類型:Symbol,表示獨一無二的值。Symbol資料類型的值是通過symbol函數生成的,每個symbol函數都是獨立的,擁有不同的傳回值。

這些類型可以直接操作儲存在變量中的實際值。

let obj1 = Symbol('a');
let obj2 = Symbol('b');
console.log(obj1); //Symbol(a)
console.log(obj2);  //Symbol(b)
console.log( obj1 == obj2);  //false
console.log(typeof obj1); //symbol
           

Symbol函數可以接受一個字元串作為參數,表示對 Symbol 執行個體的描述,主要是為了在控制台顯示,或者轉為字元串時,比較容易區分。

Symbol的作用:

  • 使用Symbol定義的變量不可以對外通路和修改
  • 使用Symbol定義的變量不可以利用for循環等進行周遊
  • Symbol函數前不能使用new指令,否則會報錯。這是因為生成的 Symbol 是一個原始類型的值,不是對象。也就是說,由于 Symbol 值不是對象,是以不能添加屬性。

2. 引用資料類型

Array、Function、Object…(在JS中除了基本資料類型以外的都是對象,資料是對象,函數是對象,正規表達式是對象,這些都是引用資料類型)

3. 基本資料類型和引用資料類型的差別

  • 聲明變量時存儲位置不同

基本資料類型:在聲明之後被儲存在棧中,因為基本資料類型的大小是固定的,所占用記憶體小,存放在棧中,友善在使用的時候進行快速查找。

引用資料類型:在聲明之後被儲存在堆中,因為引用資料類型占用記憶體空間大,且不固定,是以不能把它放在棧中,會降低變量查找的速度。但是可以将變量的位址存放在棧中,這樣當想要查找某個變量的時候,就可以先在棧中查找該變量所對應的在堆中位址,找到位址後,就可以在堆中找到該變量了。

  • 通路機制不同

由于基本資料類型和引用資料類型所存放的位置不同,是以導緻其通路的機制也不同,存放在堆中變量不可以直接通路,需要先在棧中找到相應的位址,然後再根據位址在堆中進行查找,而基本資料類型的值則可以直接找到。

  • 複制機制不同

基本資料類型:在将一個儲存着基本資料類型的變量複制給另一個變量時,會将原始值的副本指派給新變量,此後這兩個變量是完全獨立的,他們隻是擁有相同的value而已。

引用資料類型:在将一個儲存着對象記憶體位址的變量複制給另一個變量時,會把這個記憶體位址指派給新變量,也就是說這兩個變量都指向了堆記憶體中的同一個對象,他們中任何一個作出的改變都會反映在另一個身上。

複制對象時并不會在堆記憶體中新生成一個一模一樣的對象,隻是多了一個指向這個對象的指針。

  • 參數傳遞的方式不同

基本資料類型:隻是把變量裡的值傳遞給參數,之後參數和這個變量互不影響。

引用資料類型:傳遞的值是記憶體位址。

在面試的過程中,有被問到過var、let、const的差別,當說到const定義的值是不可以被改變的時候,面試官産生了疑問,問我為什麼,定義一個數組,可以通過數組的一些方法改變變量的值嘛,我猶豫了,好像确實可以,但卻說不出來為什麼,現在終于搞懂了:

原來用const定義的基本資料類型确實不可以被修改,而定義的引用資料類型是可以被修改的,const僅保證指針不發生改變,修改對象的屬性不會改變對象的指針,是以是被允許的。也就是說用const定義的引用類型隻要指針不發生改變,其他的不論如何改變都是允許的。