ECMAScript變量可能包含兩種不同的數(shù)據(jù)類型:基本數(shù)據(jù)類型和引用類型槽棍。基本數(shù)據(jù)類型值得是簡(jiǎn)單的數(shù)據(jù)段,而引用類型值指的是那些可能有多個(gè)值構(gòu)成的對(duì)象拇惋。
在將一個(gè)值賦給變量時(shí)周偎,解析器必須確定這個(gè)值是基本數(shù)據(jù)類型還是引用類型,有5中基本數(shù)據(jù)類型:undefined撑帖,null蓉坎,boolean,number和string 。這5中基本數(shù)據(jù)類型是按值訪問(wèn)的胡嘿,因?yàn)榭梢圆僮鞅4嬖谧兞恐械膶?shí)際值蛉艾。
引用類型的值保存在內(nèi)存中的對(duì)象,與其他語(yǔ)言不同衷敌,JavaScript不允許直接訪問(wèn)內(nèi)存中的位置勿侯,也就是說(shuō)不能直接操作對(duì)象的內(nèi)存空間。再操作對(duì)象時(shí)缴罗,實(shí)際是在操作對(duì)象的引用而不是實(shí)際的對(duì)象罐监,為此,引用類型的值是按引用訪問(wèn)的瞒爬。
注:在很多語(yǔ)言中弓柱,字符串是以對(duì)象的形式來(lái)表示的,因此被認(rèn)為是引用類型侧但,但是ECMAScript放棄了這一傳統(tǒng)矢空。
1.1動(dòng)態(tài)屬性
定義基本數(shù)據(jù)類型和引用類型值得方式是類似的:創(chuàng)建一個(gè)變量并為該變量賦值。但是當(dāng)這個(gè)值保存到該變量中之后禀横,對(duì)不同的類型值可以執(zhí)行的操作則大相徑庭屁药。引用類型可以添加、修改柏锄,刪除屬性和方法酿箭。但是基本屬性類型則不可以。
var person = new Object();
person.name = "lihui";
alert(person.name);//"lihiui"
以上代碼創(chuàng)建了一個(gè)對(duì)象并將其保存在了變量person中趾娃。然后缭嫡,我們?yōu)樵搶?duì)象添加了一個(gè)name屬性,并將lihui賦值上去抬闷,只想對(duì)象不銷毀妇蛀,這個(gè)屬性就會(huì)一直存在。
但是笤成,我們不能給基本數(shù)據(jù)類型添加屬性评架,盡管這樣做不會(huì)導(dǎo)致任何錯(cuò)誤。比如:
var ? name = "lihui"炕泳;
name.age = 10;
alert(name.age);//undefined
1.2復(fù)制變量值
? ? 除了保存的方式不同之外纵诞,在從一個(gè)變量想向另一個(gè)變量復(fù)制基本數(shù)據(jù)類型和引用類型值時(shí),也存在著不同培遵≌丬剑基本數(shù)據(jù)類型會(huì)被考別一份放到一個(gè)新的內(nèi)存中登刺,但是引用類型則是復(fù)制了一份只想同一塊內(nèi)存的指針。兩者有很大的差別茁裙。
1.基本數(shù)據(jù)類型復(fù)制
var number = 5;
var number2 = number;
number2 = 6;
alert(number); // 5
這個(gè)時(shí)候number 和number2 是安全沒(méi)有關(guān)系的兩個(gè)變量塘砸,分別在兩個(gè)不同的內(nèi)存空間节仿,修改任何一個(gè)變量晤锥,對(duì)另外一個(gè)都沒(méi)有影響。
2.引用類型復(fù)制
當(dāng)從一個(gè)變量向另一個(gè)變量復(fù)制引用類型的時(shí)候廊宪,同樣也會(huì)將存儲(chǔ)在變量對(duì)象中的值復(fù)制一份放到為新變量分配的空間中矾瘾。不同的是,這個(gè)值得副本實(shí)際上是一個(gè)指針箭启,而這個(gè)指針指向儲(chǔ)存在堆中的一個(gè)對(duì)象壕翩,復(fù)制操作結(jié)束后兩個(gè)變量實(shí)際上引用同一個(gè)對(duì)象。因此傅寡,改變其中一個(gè)變量放妈,就會(huì)影響另一個(gè)變量。
var obj1 = new Object();
var obj2 = obj1;
obj1.name = "zhangsan";
obj2.name = "lisi";
alert(obj1.name);// lisi
3.傳遞參數(shù)
? ?ECMAScript 中所有的函數(shù)的參數(shù)都是按值傳遞的荐操。也就是說(shuō)把函數(shù)外部的值復(fù)制給函數(shù)內(nèi)部的參數(shù)芜抒,就和把值從一個(gè)變量復(fù)制到另一個(gè)變量一樣⊥衅簦基本數(shù)據(jù)類型的傳遞如同基本數(shù)據(jù)類型變量的復(fù)制一樣宅倒,而引用類型的傳遞,則如同引用類型變量的復(fù)制一樣屯耸。
在向參數(shù)傳遞基本類型的值時(shí)拐迁,被傳遞的值會(huì)被復(fù)制給一個(gè)局部變量,(即命名參數(shù))疗绣。在向參數(shù)傳遞引用類型的值時(shí)线召,會(huì)把這個(gè)值在內(nèi)存中的地址復(fù)制給一個(gè)局部變量,因此這個(gè)局部變量的變化會(huì)反映在函數(shù)的外部多矮。請(qǐng)看下面的例子:
function addTen (num){
num += 10;
return num;
}
var count ?= 20;
var result = addTen (count);
alert(count); ?//20 ?沒(méi)有變化
alert(result); ? //30?
解釋:這里的函數(shù)addTen()有一個(gè)參數(shù)num 灶搜,而參數(shù)實(shí)際上是函數(shù)的局部變量。在調(diào)用這個(gè)函數(shù)時(shí)工窍,變量count作為參數(shù)被傳遞給函數(shù)割卖,這個(gè)變量的值是20.于是,數(shù)值20被復(fù)制給參數(shù)num以便在addTen()中使用患雏。在函數(shù)內(nèi)部鹏溯,參數(shù)num的值被加上了10,但是這一變化不會(huì)影響函數(shù)外部的count變量淹仑。參數(shù)num和count互不相識(shí)丙挽,他們僅僅是具有相同的值肺孵。假如num是按引用傳遞的話,那么變量count的值也將變成30颜阐,從而反應(yīng)函數(shù)內(nèi)部的修改平窘。當(dāng)然使用數(shù)值等基本數(shù)據(jù)類型值來(lái)說(shuō)明按值傳遞參數(shù)比較簡(jiǎn)單,但是如果使用對(duì)象凳怨,那么問(wèn)題就不怎么好解釋了瑰艘。再舉個(gè)例子:
function setName () {
obj.name = "Nicholas";
}?
var person ?= new Object();
setName (person);
alert (person.name); ? // ?“Nicholas”
? ? ?以上代碼創(chuàng)建一個(gè)對(duì)象,并將其保存在了變量person中肤舞。然后紫新,這個(gè)變量被傳遞到setName ()函數(shù)中之后就被復(fù)制給了obj。在函數(shù)內(nèi)部李剖,obj和person 引用的是同一個(gè)對(duì)象芒率。換句話說(shuō),及時(shí)這個(gè)變量是按值傳遞的篙顺,obj也會(huì)按引用來(lái)訪問(wèn)同一個(gè)對(duì)象偶芍。于是,當(dāng)在函數(shù)內(nèi)部為obj添加name屬性后德玫,函數(shù)外部的person也將有所反映匪蟀;因?yàn)閜erson指向的對(duì)象在堆內(nèi)存中只有一個(gè),而且是全局對(duì)象化焕,有許多開發(fā)人員錯(cuò)誤的認(rèn)為:在局部作用域中修改的對(duì)象會(huì)在全局作用域中反映出來(lái)萄窜,就說(shuō)明參數(shù)是按引用傳遞的。為了證明對(duì)象是按值傳遞的撒桨,下面這個(gè)例子說(shuō)明
function setName ?(obj) {
? ? ?obj.name = "Nicholas";
? ? ?obj = new Object();
? ? ?obj.name = "zhangsan";
}
var person? = new Object();
setName (person);
alert (person.name); ? // ?“Nicholas”
4.檢測(cè)類型
typeof 是檢測(cè)變量類型的最佳工具
var s = "Nicholas";
var b = true;
var i = 22;
var u;
var n = null;
var o = new Object();
alert(typeof s);// string
alert(typeof i);// number
alert(typeof b);//boolean
alert(typeof u);//undefined
alert(typeof o); //object
通常查刻,我們并不是想知道某個(gè)值是對(duì)象,而是想知道他是什么類型的對(duì)象凤类。為此穗泵,ECMAScript提供了instanceof 操作符,其語(yǔ)法是:
result = variable instanceof constructor
成立則返回TRUE谜疤;
alert(person instanceof Object);//變量person是 Object嗎佃延? 是的話返回true;