javascript——基本類型和引用類型

基本類型和引用類型的值:
基本類型的值:
基本類型的值指的是簡單的數據段,在將一個值賦給變量時,解析器必須確定這個值是基本類型的值還是引用類型的值,javascript中有5中常見的基本數據類型:Undefined、Null、Boolean、Number、和String,這5中基本數據類型是按值訪問的,因爲可以操作保存在變量中實際的值。
引用類型:
引用類型的值是指哪些可能由多個值構成的對象,引用類型的值是保存在內存中的對象,與其他語言不同,javascript不允許直接訪問內存中的位置,換言之就是javascript不允許我們直接操作對象的內存空間。在操作對象時,實際上是在操作對象的引用而不是實際的對象,因此,引用類型的值是按引用訪問的。
動態的屬性:
定義基本類型值和引用類型值的方式是類似的:創建一個變量併爲該變量賦值,但是,當這個值保存到變量中以後,對不同類型值可以執行的操作則大相徑庭,對於引用類型的值,我們可以爲其添加屬性和方法,也可以改變和刪除其屬性和方法。
實例代碼如下:
var person = new Object();
person.name = "zhang";
alert(person.name);		//zhang
上面的實例中就是一個簡單的引用類型,對於引用類型的值我們可以爲其添加屬性和方法,上例中我們創建了一個對象並保存在了變量person中,然後爲這個變量添加了一個屬性name,因爲這種是引用類型所以可以爲其添加屬性,但是如果是基本類型的值呢!?我們是不是也能添加屬性或方法呢!?來看看下面這個實例:
var work = "IT";
work.time = "3";
alert(work.time);
我們運行上面的代碼來看看結果是什麼如下圖:
我們可以看見控制檯上並沒有報錯,但是彈出的確實undefined。所以可以總結出我們在給基本類型值添加屬性或方法是雖然在瀏覽器的控制檯上並不會報錯但是代碼運行時發現該屬性不見了。這就說明了基本類型值是不能夠添加屬性或方法的,但是引用類型值可以動態添加屬性或方法,以方便我們後期的調用。
複製變量值:
複製基本類型值:
我們在上面提到過基本類型值的存儲方式是有區別的,另外就是在複製變量的值也存在一定的區別,如果我們從一個變量向另一個變量複製基本類型的值,會在變量對象上創建一個新值,然後把該值複製到爲新變量分配的位置上。
實例代碼部分如下:
var name1 = "zhang";
var name2 = name1;
alert(name1);	//zhang
alert(name2);	//zhang
由上面代碼可見我們將name1的值賦給了name2此時雖然name1與name2的值是一樣的,但是他們卻是彼此獨立的,後面調用的時候也是相互之間不影響的,也就是相當於將name1的值重新複製了一份,然後將這個重新複製一份的值給了name2。
上面我們講的只是複製基本類型值,那麼該如何複製引用類型值呢!?
複製引用類型值:
當從一個變量向另一個變量複製引用類型的值時,同樣也會將存儲在變量對象的值複製一份到爲新變量分配的空間中。
實例代碼如下:
var myfile1 = new Object();
var myfile2 = myfile1;
myfile1.name = "zhang";
alert(myfile2.name);		//zhang
在上面例子中我們新創建了一個實例對象,然而這個實例對象是存儲在什麼地方呢!?其實它在被創建出來後就會被存儲在內存中,然後我們可以不斷向這個實例對象中添加屬性及方法,在這裏我們僅僅只添加了name屬性,我們將新創建的對象保存在myfile1中並且將myfile1複製給了myfile2,注意我們複製給myfile2的不是任何屬性或方法,我們複製給myfile2的是保存在myfile1中新創建的實例對象,這也就意味着myfile1與myfile2同時都會指向同一個對象中,所以無論我們現在向這個新的實例對象中添加什麼屬性或方法,myfile1跟myfile2都是可以共享的。
傳遞參數:
有一點我們必須要很清楚,在javascript中所有函數的參數都是按值傳遞的。也就是說,我們可以把函數外部的值複製給函數內部的參數,這個過程就像我們將一個變量的值複製給另一個變量一樣,但是我們有時會感到迷惑,那就是如果是基本類型值的話會很容易理解,但是如果是引用類型的值那麼我們又該怎麼辦呢!?其實很簡單,就像是引用類型變量的複製一樣的。我們將新的實例對象保存的所在變量複製給參數,無論我們將新創建的實例對象複製給誰,前提有點一就是我們上面提到過的他們指向的對象都是同一個,這是無法改變的,換言之,不管我們是向這個被複制的對象添加任何屬性及方法,在外部的本體上都會有所體現。
我們先做一個按基本類型值傳遞的例子:
function myfile(num){
num+=10;
return num;
};
var myNum = 10;
var result = myfile(myNum);
alert(myNum);		//10
alert(result);		//20
由上面代碼可以看出如果我們直接alert(myNum);彈出的值就是10,因爲在則行這句代碼的時候跟隨着作用域鏈向上找的化變量myNum的值就是10,而我們如果將變量myNum當參數傳遞給函數是,現在就是相當於將myNum複製給了num所以這就是按值傳遞的結果彈出的是20。
那麼我們來看看如果是按對象傳值呢!?
(代碼段一:)
function myfile(obj){
obj.name = "zhang";
};
var myself = new Object();
myfile(myself);
alert(myself.name);		//zhang
如上代碼,彈出的結果爲“zhang”這個是怎麼運行的呢!?是的,我們在外部中並沒有爲myself添加新的屬性,但是當我們將保存的有新實例對象的變量當作參數傳遞給myfile函數的時候,這時的代碼可以如同下面:
(代碼段二:)
var myself = new Object();
var obj = myself;
obj.name = "zhang";
alert(myself.name);	//zhang
上面兩段代碼其實是等效的,運行原理也是一樣的,只不過在在代碼段一種是將obj變成了參數,但是在函數的內部它依然還是一個局部變量,所以無論它的形式怎麼變其結果還是兩個變量都指向了同一個內存對象中的,不管我們給兩個變量的哪一個添加了屬性或方法,另一個變量都會得到繼承。那麼這裏有一個小問題就是在局部作用域中修改的對象會在全局作用域中反映出來,究竟是屬於按值傳遞呢!?還是按引用傳遞呢!?
我們來看看下面的代碼就明白了:
function myfile(obj){
obj.name = "zhang";	//基本類型
var obj = new Object();	//引用類型
obj.name = "hu";
};
var myself = new Object();
myfile(myself);
alert(myself.name);	//zhang
從上面的代碼中我們可以看出在局部作用域中修改的對象會在全局作用域中反映出來並不是按引用傳遞的如果是按引用傳遞的話那麼彈出的值將會是“hu”。
如有理解不當之處,歡迎各位老鐵留言指正。謝謝!!!!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章