標籤:var 引用傳遞 tool func fine 引用資料類型 div 尋找 解析
大多數人系統學習過的程式設計語言,在這些語言的學習過程中最早學到的幾個要點之一就是實值型別和參考型別的區別。下面我們來看一下在 JavaScript 中基礎資料型別 (Elementary Data Type)(Primitive Types)和參考型別(Reference Types)的區別。、
基本類型和參考型別
ECMAScript包含兩個不同類型的值:基本類型值和參考型別值。基本類型值指的是簡單的資料區段;參考型別值指由多個值構成的對象。當我們把變數賦值給一個變數時,解析器首先要做的就是確認這個值是基本類型值還是參考型別值。
常見的五種基礎資料型別 (Elementary Data Type)是:
Undifined、Null、Boolean、Number和String。這五種基礎資料型別 (Elementary Data Type)可以直接操作儲存在變數中的實際值。
看下面例子:
?
| 123456789 |
var a = 10;var b = a; b = 20;console.log(a); // 10 var bl = true;var bl1 = bl; bl1 = false;console.log(bl); // true |
上面,b擷取值是a值的一份拷貝,雖然,兩個變數的值是相等,但是兩個變數儲存兩不同的基礎資料型別 (Elementary Data Type)值。b只是儲存了a複製的一個副本。所以,當b的值改變時,a的值依然是10;
下面,兩個Boolean變數bl和bl1同樣是基礎資料型別 (Elementary Data Type),同樣儲存兩個不同的基本資料據類型值,bl1儲存bl複製的一個副本。
示範了這種基礎資料型別 (Elementary Data Type)賦值的過程:
下面看一下參考型別資料:
javascript引用資料類型是儲存在堆記憶體中的對象,與其它語言不同的是,你不可以直接存取堆記憶體空間中的位置和操作堆記憶體空間。只能通過操作對象的在棧記憶體中的引用地址。所以參考型別的資料,在棧記憶體中儲存的實際上是對象在堆記憶體中的引用地址。通過這個引用地址可以快速尋找到儲存在堆記憶體中的對象。
看下下面的例子:
?
| 1234 |
var obj1 = new Object();var obj2 = obj1;obj2.name = "我有名字了";console.log(obj1.name); // 我有名字了 |
由上面例子,我們聲明了一個引用資料類型變數obj1,並把它賦值給了另外一個引用資料類型變數obj2。當我們obj2添加了一個name屬性並賦值"我有名字了"。obj1同樣擁有了和obj2一樣的name屬性。說明這兩個引用資料類型變數指向同一個堆記憶體對象。obj1賦值給obj2,實際只是把這個堆記憶體對象在棧記憶體的引用地址複製了一份給了obj2,但它們本質上共同指向了同一個堆記憶體對象。
下面我們來示範這個引用資料類型賦值過程:
自然,給obj2添加name屬性,實際上是給堆記憶體中的對象添加了name屬性,obj2和obj1在棧記憶體中儲存的只是堆記憶體對象的引用地址,雖然也是拷貝了一份,但指向的對象卻是同一個。故而改變obj2引起了obj1的改變。
一般而言,基礎資料型別 (Elementary Data Type)是有固定數目的位元組組成,這些位元組可以在解析器的較底層進行操作比如Number和Boolean;而引用資料類型,可以包含任意數目的屬性和元素,因此它們無法像基礎資料型別 (Elementary Data Type)那樣很容易的操作。由於,引用資料類型的值是會發生變化的,所以通過跟基礎資料型別 (Elementary Data Type)一樣的值傳遞方式,也就沒什麼意義了,因為會牽涉到大量的記憶體的複製和比較,效率太低。所以引用資料類型是通過引用傳遞方式,實際傳遞的只是對象的一個地址。比如Array和Function因為它們都是特殊的對象所以它都是參考型別。另外,參考型別是可以添加屬性,基本類型雖然也可以添加屬性,也不會報錯,經測試添加完之後卻是無法訪問的。
看下面代碼:
?
| 123 |
var a = 12; a.name = "myname";console.log(a.name); // undefined |
String一個特殊的基礎資料型別 (Elementary Data Type)
在很多語言中,String是以對象的形式表示的,但在ECMAScript裡沒有沿用這種傳統,String是當作一種基礎資料型別 (Elementary Data Type),但它是一個比較特殊的基本類型。
看上去好像String應該做為一個參考型別,可實際上它不是,因為它不是對象。那麼看起來它應該是基礎資料型別 (Elementary Data Type),應該是通值傳遞的方式來操作。
看下面例子:
?
| 1234 |
var stra = "這是一個字串";var strb = stra; stra = "這是另外一個字串";console.log(strb); // 這是一個字串 |
上面例子我們看到,彷彿stra通過值傳遞的方式複製了一份給了strb。當stra改變的時候,strb並沒有改變,似乎我們已經可以下結論,String就是個基礎資料型別 (Elementary Data Type)。
可是,因為String是可以任意長度的,通過值傳遞,一個一個的複製位元組顯示效率依然很低,看起來String也可以當作參考型別。
看下面例子:
?
| 123 |
var a = "myobject"; a.name = "myname";console.log(a.name); // undefined |
顯示String無法當作一個對象來處理。實際上,javascript裡的String是不可以改變的,javascript也沒有提供任何一個改變字串的方法和文法。
?
| 123 |
var a = "myobject"; a = a.substring(3,5) console.log(a); // bj |
記住這樣做,就沒有改變String字串"myobject",只a引用了另一個字串"bj","myobject"被回收了。
所以可以這樣講,String實際上並不符合上面兩種資料類型分類。它是具有兩方面屬性介於兩都之間的一種特殊類型。
以上所述就是本文的全部內容了,希望大家能夠喜歡。
javascript中基本類型和參考型別的區別分析