JavaScript數(shù)據(jù)類型之基本類型和引用類型的值
ECMAScript變量包含兩種不同數(shù)據(jù)類型的值:基本類型值和引用類型值?;绢愋椭凳呛?jiǎn)單的數(shù)據(jù)段,而引用類型值指那些可能由多個(gè)值構(gòu)成的對(duì)象。
在將一個(gè)值賦給變量時(shí),解析器必須確定這個(gè)值是基本類型還是引用類型?;绢愋桶ㄈ鏤ndefined、Null、Boolean、Number和String,這5種基本類型數(shù)據(jù)類型是按值訪問的,因此可以操作保存在變量中的實(shí)際的值;引用類型類型的值是保存在內(nèi)存中的對(duì)象。與其他語言不同,JavaScript不允許直接訪問內(nèi)存中的位置,也就是說不能直接操作對(duì)象的內(nèi)存空間。在操作對(duì)象時(shí),實(shí)際上實(shí)在操作對(duì)象的引用而不是實(shí)際的對(duì)象,因此,引用類型的值是按引用訪問的。
1、動(dòng)態(tài)的屬性
定義基本類型和定義引用類型的方法大相近庭。對(duì)于引用類型的值,我們可以為其添加屬性和方法,也可以改變和刪除其屬性和方法,如下:
var person = new Object();
person.name = "zxj";
alert(person.name); //"zxj"
2、復(fù)制變量值
如果從一個(gè)變量向另一個(gè)變量復(fù)制基本類型的值,會(huì)在變量對(duì)象上創(chuàng)建一個(gè)新值,然后將該值復(fù)制到為新變量分配的位置上。
var num1 = 5;
var num2 = num1; //5

當(dāng)從一個(gè)變量向另一個(gè)變量復(fù)制引用類型的值時(shí),同樣也會(huì)將存儲(chǔ)在變量對(duì)象中的值復(fù)制一份放到為新變量分配的內(nèi)存空間里。不同的是,這個(gè)值實(shí)際上是一個(gè)指針,而這個(gè)指針執(zhí)行存儲(chǔ)在堆中的一個(gè)對(duì)象。復(fù)制結(jié)束后,兩個(gè)變量實(shí)際上將引用同一個(gè)對(duì)象。因此,改變其中一個(gè)變量,就會(huì)影響到另一個(gè)變量,如下所示:
var obj1 = new Object();
var obj2 = obj1;
obj1.name = "zxj";
alert(obj2.name); //"zxj"

3、傳遞參數(shù)
ESMAScript中所有函數(shù)的參數(shù)都是按值傳遞的。也就是說,把函數(shù)外部的值復(fù)制給函數(shù)內(nèi)部的參數(shù),就是把值從一個(gè)變量復(fù)制到另一個(gè)變量一樣?;绢愋椭档膫鬟f如同基本類型變量的復(fù)制一樣。引用類型值的傳遞,則如同引用類型變量的復(fù)制一樣。有不少開發(fā)者在這一點(diǎn)上可能感到困惑,因?yàn)樵L問變量有按值和按引用兩種方式,而參數(shù)只能按值傳遞。
在向參數(shù)傳遞基本類型的值時(shí),被傳遞的值會(huì)被復(fù)制給一個(gè)局部變量(即命名參數(shù))。如下代碼所示:
function addTen(num) {
num += 10;
return num;
}
var count = 20;
var result = addTen(count);
alert(count); // 20,沒有變化
alert(result); // 30
參數(shù)實(shí)際上是函數(shù)的局部變量。參數(shù)num和變量count互不認(rèn)識(shí),它們僅僅具有相同的值。假如num是按引用傳遞的,那么變量count的值也將變成30,從而反映函數(shù)內(nèi)部的變化。
在向參數(shù)傳遞引用類型的值時(shí),會(huì)把這個(gè)值在內(nèi)存中的地址復(fù)制一個(gè)給局部變量,因此這個(gè)局部變量的變化會(huì)反映在函數(shù)的外部。在這里我們使用引用類型來看一下:
function setName(obj) {
obj.name = "zxj";
}
var person = new Object();
setName(person);
alert(person.name); //"zxj"
在這個(gè)函數(shù)內(nèi)部,obj和person引用的是同一個(gè)對(duì)象。換句話說,即使這個(gè)對(duì)象是按值傳遞的,obj也會(huì)按引用來訪問同一個(gè)對(duì)象。于是,當(dāng)在函數(shù)內(nèi)部為obj添加name屬性后,函數(shù)外部的person也會(huì)有所反映,因?yàn)閜erson指向的對(duì)象在堆內(nèi)存中只有一個(gè),而且是全局對(duì)象。很多開發(fā)者錯(cuò)誤的認(rèn)為:在局部作用域中修改的對(duì)象會(huì)在全局作用域中反映出來,就說明參數(shù)是按引用傳遞的。為了證明對(duì)象是按值傳遞的,我們?cè)诳纯聪旅孢@個(gè)進(jìn)過修改的例子:
function setName(obj) {
obj.name = "zxj";
obj = new Object();
obj.name = "sdf";
}
var person = new Object();
setName(person);
alert(person.name);
上面這個(gè)例子可以看出,如過person是按引用傳遞的,那么person就會(huì)自動(dòng)被修改為指向其name屬性值為"sdf"的新對(duì)象。但是,當(dāng)接下來再訪問person.name時(shí),顯示的仍然是"zxj"。這說明即使在函數(shù)內(nèi)部修改了參數(shù)的值,但原始的引用仍然保存不變。實(shí)際上,當(dāng)在函數(shù)內(nèi)部重寫obj時(shí),這個(gè)變量引用的就是一個(gè)局部對(duì)象了。而這個(gè)局部對(duì)象會(huì)在函數(shù)執(zhí)行完畢時(shí)立即銷毀。
可以將ECMAScript函數(shù)的參數(shù)想象成局部變量。
4、檢測(cè)類型
雖然在檢測(cè)基本數(shù)據(jù)類型時(shí)typeof是一個(gè)得力助手,但是在檢測(cè)引用類型時(shí),這個(gè)操作符用處卻不大。通常,我們并不想知道某個(gè)值是對(duì)象,而是想知道他是什么類型的對(duì)象。為此ECMAScript提供了instanceof操作符,其語法如下:
result = varible instanceof constructor
如果變量是給定引用類型的實(shí)例,那么instanceof操作符會(huì)返回true:
alert(person instanceof Object);
相關(guān)文章
JavaScript基本概念初級(jí)講解論壇貼的學(xué)習(xí)記錄
JavaScript基本概念 論壇貼建議大家看下,都是一些js的高級(jí)的技巧知識(shí)小結(jié)。2009-02-02
分享5個(gè)頂級(jí)的JavaScript Ajax組件庫
AJAX是用來對(duì)服務(wù)器進(jìn)行異步HTTP調(diào)用的一系列web開發(fā)技術(shù)客戶端框架,本文為大家分享了5個(gè)頂級(jí)的JavaScript Ajax組件庫2018-09-09
簡(jiǎn)介JavaScript中的setTime()方法的使用
這篇文章主要介紹了簡(jiǎn)介JavaScript中的setTime()方法的使用,是JS入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-06-06
JS阻止冒泡事件以及默認(rèn)事件發(fā)生的簡(jiǎn)單方法
這篇文章主要介紹了JS阻止冒泡事件以及默認(rèn)事件發(fā)生的簡(jiǎn)單方法,有需要的朋友可以參考一下2014-01-01
js對(duì)象屬性的攔截與Proxy代理與Reflect映射的用法和區(qū)別講解
reflect和proxy都是JavaScript中用于處理對(duì)象的特殊API,下面這篇文章主要給大家介紹了關(guān)于js對(duì)象屬性的攔截與Proxy代理與Reflect映射的用法和區(qū)別,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-06-06
Javascript標(biāo)準(zhǔn)DOM Range操作全集
Javascript標(biāo)準(zhǔn)DOM Range操作全集...2007-01-01

