基本資料型別和複雜資料型別的本質區別
資料型別
JavaScript中的資料型別可以分為兩大類:
- 原始值 (基本型別)
- Boolean
- Null
- String
- Number
- Bigint
- Symbol
- Undefined
- 物件 (複雜型別)
- Object
- Array
- Function
小結:資料分為兩大類,物件和非物件
資料的存放
資料存放在記憶體裡面,記憶體分:棧區(stack),堆區(heap)。
棧區
棧區的特點是:資料按順序存放,記憶體大小由系統分配。
基本型別的存放示意圖:

堆記憶體
堆記憶體的特點是:資料隨機存放,大小由程式設計師分配。
複雜型別的存放示意圖:

行為差異
賦值
基本型別賦值
var a = 1
var b = a
b = 0
console.log(a) // 1
複製程式碼

在棧記憶體中的資料發生複製行為時,系統會自動為新的變數分配一個新值。var b = a執行之後,a與b雖然值都等於1,但是他們其實已經是相互獨立互不影響的值了,所以我們修改了b的值以後,a的值並不會發生變化。
複雜資料型別
var o1 = {name:"o1"}
var o2 = o1
o2.name = "o2"
console.log(o1.name)// o2
複製程式碼

求值策略
所謂求值策略也就是函式的傳參方式,函式的引數可能是基本型別也可能是複雜型別,這兩種型別在傳參的時候有所區別。
按值傳遞
按值傳遞,引數的值是呼叫者傳遞的值的拷貝(copy of value),函式內部改變引數的值不會影響到外面的值,一般來說,是重新分配了新記憶體,該新記憶體塊的值是外部值的拷貝,並且它的值是用到函式內部的。
var a = 1
function changeA (a) {
a = 2
}
changeA()
console.log(a)// 1
複製程式碼
這說明了,函式內部的a和函式外部的a是相互獨立的,傳參是將值拷貝一份。
那麼對於複雜型別的傳參呢。網上有各種各樣的教程和文章,有的說按引用傳遞,什麼共享傳遞,等等,其實很簡單的道理,明白了上面的記憶體的分配,就很清楚的知道是怎麼回事了,至於是叫按共享傳遞(Call by sharing)還是什麼其他的都不重要。
還是按值傳遞
對於基本型別已經搞清楚了,傳參的方式是按值傳遞,現在看複雜型別的傳參:


總結:在函式傳參的時候,不管是基本型別還是複雜型別,都是按值傳遞,對於基本型別是拷貝值也就是資料本身,而對於複雜型別,拷貝的是複雜型別在堆記憶體中的地址。