JavaScript 基本資料型別和引用型別的區別詳解
前兩天看到kraaas
大神的關於基本資料型別和引用型別的區別的文章覺得寫得非常不錯,就想著在其基礎上加上自己平時看到的一些知識點和理解,所以就有了以下的文章
js基本資料型別:
js基本資料型別包括:undefined,null,number,boolean,string.基本資料型別是按值訪問的,就是說我們可以操作儲存在變數中的實際的值
1. 基本資料型別的值是不可變的
任何方法都無法改變一個基本型別的值,比如一個字串:
var name = "change"; name.substr();//hang console.log(name);//change var s = "hello"; s.toUpperCase()//HELLO; console.log(s)//hello
通過這兩個例子,我們會發現原先定義的變數name的值始終沒有發生改變,而呼叫substr()和toUpperCase()方法後返回的是一個新的字串,跟原先定義的變數name並沒有關係
或許有人會有以下的疑問,看程式碼:
var name = "change"; name = "change1"; console.log(name)//change1
這樣看起來name的值“改變了”其實,var name = “change”,這裡的基礎型別是string,也就是”change”,這裡的”change”是不可以改變的,name只是指向”change”的一個指標,指標的指向可以改變,所以你可以name = “change1″.此時name指向了”change1″,同理,這裡的”change1″同樣不可以改變
也就是說這裡你認為的改變只是“指標的指向改變”
這裡的基礎型別指的是”change”,而不是name,要區分清楚
2. 基本資料型別不可以新增屬性和方法
var p = "change"; p.age = 29; p.method = function(){console.log(name)}; console.log(p.age)//undefined console.log(p.method)//undefined
通過上面的程式碼,我們知道不能給基本型別新增屬性和方法,也再次說明基本型別是不可變的
3. 基本資料型別的賦值是簡單賦值
如果從一個變數向另一個變數賦值基本型別的值,會在變數物件上建立一個新值,然後把該值複製到為新變數分配的位置上
var a = 10; var b = a; a++; console.log(a)//11 console.log(b)//10
上面的程式碼中,a中儲存的值是10.當使用a的值來初始化b時,b中也儲存了值10.但b中的10和a中的10是完全獨立的.b中的值知識a中值的一個副本.所以這兩個變數可以參與任何操作而不會相互影響.如下圖:
4. 基本資料型別的比較是值的比較
var person1 = '{}'; var person2 = '{}'; console.log(person1 == person2); // true
5. 基本資料型別是存放在棧區的
假如有以下幾個基本型別的變數:
var name = "jozo"; var city = "guangzhou"; var age = 22;
那麼它的儲存結構如下圖:
棧區包括了變數的識別符號和變數的值
js引用型別:
js中除了上面的基本型別之外就是引用型別了,也可以說就是物件了,比如:Object,Array,Function,Data等
1. 引用型別的值是可以改變的
var o = {x:1}; o.x = 2;//通過修改物件屬性值更改物件 o.y = 3;再次更改物件,給它增加一個屬性 var a = [1,2,3]; a[0] = 0;//更改陣列的一個元素 a[3] = 4;//給陣列增加一個元素
2. 引用型別可以新增屬性和方法
var person = {}; person.name = "change"; person.say = function(){alert("hello");} console.log(person.name)//change console.log(person.say)//function(){alert("hello");}
3. 引用型別的賦值是物件引用
先看以下程式碼:
var a = {}; var b= a; a.name = "change"; console.log(a.name)//change; console.log(b.name)//change b.age = 29; console.log(a.age)//29 console.log(b.age)//29
當從一個變數向另一個變數賦值引用型別的值時,同樣也會將儲存在變數中的物件的值複製一份放到為新變數分配的空間中.引用型別儲存在變數中的是物件在堆記憶體中的地址,所以,與基本資料型別的簡單賦值不同,這個值的副本實際上是一個指標,而這個指標指向儲存在堆記憶體的一個物件.那麼賦值操作後,兩個變數都儲存了同一個物件地址,而這兩個地址指向了同一個物件.因此,改變其中任何一個變數,都會互相影響
他們的關係如下圖:
因此,引用型別的賦值其實是物件儲存在棧區地址指標的賦值,所以兩個變數指向同一個物件,任何的操作都會互相影響。
4. 引用型別的比較是引用的比較
var person1 = {}; var person2 = {}; console.log(person1 == person2)//false
為什麼兩個物件看起來一摸一樣,但是卻不相等呢?
因為引用型別的比較是引用的比較,換句話說,就是比較兩個物件儲存在棧區的指向堆記憶體的地址是否相同,此時,雖然p1和p2看起來都是一個”{}”,但是他們儲存在棧區中的指向堆記憶體的地址卻是不同的,所以兩個物件不相等
5. 引用型別是同時儲存在棧區和堆區中的
引用型別的儲存需要在記憶體的棧區和堆區共同完成,棧區儲存變數識別符號和指向堆記憶體的地址
假如有以下幾個物件:
var person1 = {name:"change1"}; var person2 = {name:"change2"}; var person3 = {name:"change3"};
則這三個物件在記憶體中儲存的情況如下圖:
基本包裝型別(包裝物件):
先看下以下程式碼:
var s1 = "helloworld"; var s2 = s1.substr(4);
上面我們說到字串是基本資料型別,不應該有方法,那為什麼這裡s1可以呼叫substr()呢?
通過翻閱js權威指南第3.6章節和高階程式設計第5.6章節我們得知,ECMAScript還提供了三個特殊的引用型別Boolean,String,Number.我們稱這三個特殊的引用型別為基本包裝型別,也叫包裝物件.
也就是說當讀取string,boolean和number這三個基本資料型別的時候,後臺就會建立一個對應的基本包裝型別物件,從而讓我們能夠呼叫一些方法來操作這些資料.
所以當第二行程式碼訪問s1的時候,後臺會自動完成下列操作:
- 建立String型別的一個例項;// var s1 = new String(“helloworld”);
- 在例項上呼叫指定方法;// var s2 = s1.substr(4);
- 銷燬這個例項;// s1 = null;
正因為有第三步這個銷燬的動作,所以你應該能夠明白為什麼基本資料型別不可以新增屬性和方法,這也正是基本裝包型別和引用型別主要區別:物件的生存期.使用new操作符建立的引用型別的例項,在執行流離開當前作用域之前都是一直儲存在記憶體中.而自動建立的基本包裝型別的物件,則只存在於一行程式碼的執行瞬間,然後立即被銷燬。
相關文章
- js基本型別和引用型別區別JS型別
- 區別值型別資料和引用型別資料型別
- js資料型別之基本資料型別和引用資料型別JS資料型別
- JAVA中基本資料型別和引用資料型別Java資料型別
- JavaScript - 基本型別與引用型別值JavaScript型別
- 從賦值看基本型別和引用型別的區別賦值型別
- Java的基本型別和引用型別Java型別
- JavaScript值型別和引用型別JavaScript型別
- 基本資料型別與API引用型別的使用資料型別API
- Java中的基本資料型別與引用資料型別Java資料型別
- 你不知道的JavaScript--Item4 基本型別和基本包裝型別(引用型別)JavaScript型別
- 《JavaScript物件導向精要》之一:基本型別和引用型別JavaScript物件型別
- JS篇-基本型別和引用型別、typeofJS型別
- JavaScript筆記5:計時器、物件、基本資料型別、引用資料型別JavaScript筆記物件資料型別
- c#中值型別和引用型別的區別C#型別
- JavaScript 資料型別與型別判斷詳解JavaScript資料型別
- JavaScript引用型別-Object型別JavaScript型別Object
- JavaScript——資料型別詳解JavaScript資料型別
- javascript原始值和引用值型別及區別JavaScript型別
- JavaScript基本資料型別JavaScript資料型別
- 值型別與引用型別的區別型別
- javascript:引用型別JavaScript型別
- 基本資料型別與引用資料型別,及記憶體分配資料型別記憶體
- 值型別和引用型別型別
- Java中基本資料型別和包裝型別有什麼區別?Java資料型別
- Golang的值型別和引用型別的範圍、儲存區域、區別Golang型別
- JavaScript基本資料型別之undefined和nullJavaScript資料型別UndefinedNull
- 基本資料型別與字串型別資料型別字串
- JavaScript基本資料型別有哪些JavaScript資料型別
- JavaScript 基本資料型別轉換JavaScript資料型別
- C++引用型別詳解C++型別
- JavaScript變數與資料型別詳解JavaScript變數資料型別
- 基本資料型別資料型別
- JavaScript 基礎 (二) - 引用資料型別 (物件)JavaScript資料型別物件
- JavaScript 基礎 (一) - 基本資料型別JavaScript資料型別
- 簡單資料型別和引用資料型別對應棧和堆示意圖資料型別
- Python基本資料型別:布林型別(Boolean)Python資料型別Boolean
- javaScript的資料型別JavaScript資料型別
- JavaScript資料型別JavaScript資料型別