數(shù)據(jù)類型
- ECMAScript變量包含兩種不同類型的值:基本類型值、引用類型值;
- 基本類型值:指的是保存在棧內(nèi)存中的簡單數(shù)據(jù)段;
- 引用類型值:指的是那些保存在堆內(nèi)存中的對象,意思是,變量中保存的實際上只是一個指針,這個指針指向內(nèi)存堆中實際的值;
兩種訪問方式
- 基本類型值:按值訪問,操作的是他們實際保存的值;
- 引用類型值:按引用訪問,當(dāng)查詢時,我們需要先從棧中讀取內(nèi)存地址,然后再順藤摸瓜地找到保存在堆內(nèi)存中的值;
兩種類型復(fù)制
基本類型變量的復(fù)制:
從一個變量向一個變量復(fù)制時,會在棧中創(chuàng)建一個新值,然后把值復(fù)制到為新變量分配的位置上,改變源數(shù)據(jù)不會影響到新的變量(互不干涉);
引用類型變量的復(fù)制:
復(fù)制的是存儲在棧中的指針,將指針復(fù)制到棧中為新變量分配的空間中,而這個指針副本和原指針執(zhí)行存儲在堆中的同一個對象,復(fù)制操作結(jié)束后,兩個變量實際上將引用同一個對象;因此改變其中的一個,將影響另一個;
函數(shù)參數(shù)的傳遞
1、ECMA中所有函數(shù)的參數(shù)都是按值傳遞的
在向參數(shù)傳遞基本類型的值時,被傳遞的值會被復(fù)制給一個局部變量,在向參數(shù)傳遞引用類型的值時,會把這個值在內(nèi)存的地址復(fù)制給一個局部變量
基本數(shù)據(jù)類型傳遞參數(shù)
funciton addTen(num){
num+=10;
return num;
}
var count=20;
var result=addTen(count);
alert(count);//20
alert(resullt);//30
執(zhí)行結(jié)果是:20和30。
在這段代碼中,將變量count當(dāng)做參數(shù)傳遞給了函數(shù)addTen,也就是相當(dāng)于將變量count的值復(fù)制給了函數(shù)addTen的參數(shù)。這時addTen的參數(shù)num可以看做是函數(shù)內(nèi)部的一個變量。
在上段代碼中,就相當(dāng)于兩個基本數(shù)據(jù)類型變量之間的值復(fù)制。而基本數(shù)據(jù)類型都有自己獨立的內(nèi)存地址,所以num和count是沒有任何關(guān)系的,他們只是值相等而已,函數(shù)執(zhí)行完畢后,count的值并沒有改變。
而函數(shù)外面的result是被直接賦值的,所以result的值就是函數(shù)的結(jié)果30。
引用類型傳遞參數(shù)
function setName(obj){
obj.name="LSN";
}
var person=new Object();
setName(person);
alert(person.name); // LSN
執(zhí)行結(jié)果是:LSN。
在這段代碼中,函數(shù)setName的作用是給obj對象添加了一個屬性name,并給該屬性賦值為"LSN",因為obj是引用類型,所以這里屬于是將引用類型person賦值給了obj,也就是說person和obj引用了一個內(nèi)存地址,所以當(dāng)給obj新加了屬性name時,在函數(shù)外面的person也跟著改變,最后person.name的結(jié)果為LSN。
引用類型傳遞參數(shù)到底傳的是值還是引用
function setName(obj){
obj.name="ABC";
obj=new Object();
obj.name="BCD";
}
var person=new Object();
setName(person);
alert(person.name); // ABC
執(zhí)行結(jié)果是:ABC。
實例3與實例2的區(qū)別是在函數(shù)中又加了2行代碼,在給obj對象新加一個屬性name并賦值后又將obj定義成了一個新的對象(new Object()),定義新對象后又name賦上新的值“BCD”。
這個時候如果是按引用傳遞的話,那么最后person對象就會自動修改為指向其name屬性為"BCD"的新對象,但最后顯示的卻是“ABC”,這說明即使在函數(shù)內(nèi)部修改了參數(shù)的值,但原始的引用還保持不變。
實際上,當(dāng)在函數(shù)內(nèi)部obj=new Object()時 這個新的obj就已經(jīng)成為函數(shù)內(nèi)部的局部對象了,這個對象會在函數(shù)執(zhí)行完畢后自動銷毀。
兩種變量類型檢測
- typeof操作符是檢測基本類型的最佳工具;
- 如果變量值是nul或者對象,typeof 將返回“object”;
- Instanceof用于檢測引用類型,可以檢測到具體的,它是什么類型的實例;
- 如果變量是給定引用類型的實例,instanceof操作符會返回true;
補充:基本包裝類型(包裝對象)
先看下以下代碼:
var s1 = "helloworld";
var s2 = s1.substr(4);
上面我們說到字符串是基本數(shù)據(jù)類型,不應(yīng)該有方法,那為什么這里s1可以調(diào)用substr()呢?
ECMAScript還提供了三個特殊的引用類型Boolean,String,Number。我們稱這三個特殊的引用類型為基本包裝類型,也叫包裝對象。
也就是說當(dāng)讀取string,boolean和number這三個基本數(shù)據(jù)類型的時候,后臺就會創(chuàng)建一個對應(yīng)的基本包裝類型對象,從而讓我們能夠調(diào)用一些方法來操作這些數(shù)據(jù).
所以當(dāng)?shù)诙写a訪問s1的時候,后臺會自動完成下列操作:
- 創(chuàng)建String類型的一個實例;
// var s1 = new String("helloworld"); - 在實例上調(diào)用指定方法;
// var s2 = s1.substr(4); - 銷毀這個實例;
// s1 = null;
正因為有第三步這個銷毀的動作,所以基本數(shù)據(jù)類型不可以添加屬性和方法,這也正是基本裝包類型和引用類型主要區(qū)別:對象的生存期。
使用new操作符創(chuàng)建的引用類型的實例,在執(zhí)行流離開當(dāng)前作用域之前都是一直保存在內(nèi)存中。自動創(chuàng)建的基本包裝類型的對象,則只存在于一行代碼的執(zhí)行瞬間,然后立即被銷毀。
