基本類型和引用類型的值
基本類型值指的是簡(jiǎn)單的數(shù)據(jù)段,而引用類型值指的是那些可能由多個(gè)值構(gòu)成的對(duì)象祭陷。
javascript不允許直接訪問(wèn)內(nèi)存中的位置,也就是說(shuō)不能直接操作對(duì)象的內(nèi)存空間趣席。
在很多語(yǔ)言中兵志,字符串以對(duì)象的形式表示,因此被認(rèn)為是引用類型的宣肚。ECAMScript放棄了這一傳統(tǒng)想罕。
動(dòng)態(tài)的屬性
對(duì)于引用類型的值,我們可以添加霉涨、改變和刪除其屬性和方法按价。
復(fù)制變量值
從一個(gè)變量向另一個(gè)變量復(fù)制基本類型的值惭适,會(huì)在變量對(duì)象上創(chuàng)建一個(gè)新值,然后把該值復(fù)制到為新變量分配的位置上俘枫。
var num1 =5;
var num2 =num1;
num1和num2中的5是完全獨(dú)立的腥沽,num2中的5只是num1中5的一個(gè)副本。
從一個(gè)變量向另一個(gè)變量復(fù)制引用類型的值鸠蚪,同樣也會(huì)將存儲(chǔ)在變量對(duì)象中的值復(fù)制一份放到新變量分配的空間中今阳。不同的是,這個(gè)值的副本實(shí)際上是一個(gè)指針茅信。
var obj1 = new Object();
var obj2 = obj1;
obj1.name = 'asdf';
alert(obj2.name); //asdf
傳遞參數(shù)
ECMAScript中所有函數(shù)的參數(shù)都是按值傳遞的盾舌。
function addTen (num) {
num +=10;
return num;
}
var count = 20;
var result = addTen(count);
alert(count); //20,沒(méi)有變化
function setName(obj) {
obj.name = 'asdf';
}
var person = new Object();
setName(person);
alert(person.name); //asdf
很多人錯(cuò)誤的認(rèn)為:在局部作用域中修改的對(duì)象會(huì)在全局作用域中反映出來(lái),就說(shuō)明參數(shù)是按引用傳遞的蘸鲸⊙矗看下面的例子:
function setName(obj) {
obj.name = 'asdf';
obj = new Object();
obj.name = 'qwer';
}
var person = new Object();
setName(person);
alert(person.name); //asdf
檢測(cè)類型
typeof
操作符用來(lái)檢測(cè)變量是不是基本類型。
instanceof
操作符用來(lái)檢測(cè)引用類型酌摇。
alert(person instanceof Objcet);
使用
typeof
操作符檢測(cè)函數(shù)是膝舅,會(huì)返回function。在Safari 5及之前版本和Chrome7之前版本中使用typeof
檢測(cè)正則表達(dá)式時(shí)窑多,由于規(guī)范的原因仍稀,這個(gè)操作符也會(huì)返回function。ECMA-262規(guī)定任何內(nèi)部實(shí)現(xiàn)[[call]]方法的對(duì)象都應(yīng)該在應(yīng)用typeof
操作符時(shí)返回function埂息。在IE和Firefox中技潘,對(duì)正則表達(dá)式應(yīng)用typeof
時(shí)會(huì)返回Object。
執(zhí)行環(huán)境及作用域
執(zhí)行環(huán)境(execution context)定義了變量或函數(shù)有權(quán)訪問(wèn)的其他數(shù)據(jù)千康,決定了它們各自的行為享幽。每個(gè)執(zhí)行環(huán)境都有一個(gè)與之關(guān)聯(lián)的變量對(duì)象(variable object),環(huán)境中定義的所有變量和函數(shù)都保存在這個(gè)對(duì)象中拾弃。雖然我們編寫的代碼訪問(wèn)不到值桩,但解析器在處理數(shù)據(jù)時(shí)會(huì)在后臺(tái)使用它。
全局執(zhí)行環(huán)境是最外圍的一個(gè)執(zhí)行環(huán)境豪椿。根據(jù)ECMAScript實(shí)現(xiàn)所在宿主環(huán)境不同颠毙,表示執(zhí)行環(huán)境的對(duì)象也不一樣。在Web瀏覽器中砂碉,全局執(zhí)行環(huán)境被認(rèn)為是window對(duì)象蛀蜜,因此所有全局變量和函數(shù)都是作為window對(duì)象的屬性和方法創(chuàng)建的。某個(gè)執(zhí)行環(huán)境中的所有代碼執(zhí)行完畢后增蹭,該環(huán)境被銷毀滴某,保存在其中的所有變量和函數(shù)定義也隨之銷毀(全局執(zhí)行環(huán)境直到應(yīng)用程序退出--例如關(guān)閉網(wǎng)頁(yè)或?yàn)g覽器--時(shí)才會(huì)被銷毀)。
每個(gè)函數(shù)都有自己的執(zhí)行環(huán)境。
當(dāng)代碼在一個(gè)環(huán)境中執(zhí)行時(shí)霎奢,會(huì)創(chuàng)建變量對(duì)象的一個(gè)作用域鏈(scope chain)户誓。作用域鏈的用途是保證對(duì)執(zhí)行環(huán)境有權(quán)訪問(wèn)的所有變量和函數(shù)的有序訪問(wèn)。作用域鏈的前端幕侠,始終都是當(dāng)前執(zhí)行的代碼所在環(huán)境的變量對(duì)象帝美。如果這個(gè)環(huán)境是函數(shù),則將其活動(dòng)對(duì)象(activation object)作為變量對(duì)象晤硕〉刻叮活動(dòng)對(duì)象在最開始時(shí)只包含一個(gè)變量,即arguments對(duì)象(這個(gè)對(duì)象在全局環(huán)境中是不存在的)舞箍。全局執(zhí)行環(huán)境的變量對(duì)象始終都是作用域鏈中的最后一個(gè)對(duì)象舰褪。
延長(zhǎng)作用域鏈
雖然執(zhí)行環(huán)境只有兩種:全局和局部(函數(shù)),但還有其他辦法來(lái)延長(zhǎng)作用域鏈疏橄。因?yàn)橛行┱Z(yǔ)句可以在作用域鏈的前端臨時(shí)增加一個(gè)變量對(duì)象占拍,該變量對(duì)象會(huì)在代碼執(zhí)行后被移除。具體來(lái)說(shuō)捎迫,就是當(dāng)執(zhí)行流進(jìn)入下列任何一個(gè)語(yǔ)句時(shí)晃酒,作用域鏈就會(huì)得到加長(zhǎng):
- try-catch語(yǔ)句的catch塊
- with語(yǔ)句
對(duì)于with語(yǔ)句來(lái)說(shuō),會(huì)將指定的對(duì)象添加到作用域鏈中窄绒。對(duì)catch語(yǔ)句來(lái)說(shuō)贝次,會(huì)創(chuàng)建一個(gè)新的變量對(duì)象,其中包含的是被拋出的錯(cuò)誤對(duì)象的聲明颗祝。
function buildUrl () {
var qs = "?debug=true";
with (location) {
var url = href + qs;
}
return url;
}
在IE8及之前版本的JavaScript實(shí)現(xiàn)中,存在一個(gè)與標(biāo)準(zhǔn)不一致的地方恼布,即catch語(yǔ)句中捕獲的錯(cuò)誤對(duì)象會(huì)被添加到執(zhí)行環(huán)境的變量對(duì)象螺戳,而不是catch語(yǔ)句的變量對(duì)象中。換句話折汞,即使是在catch塊的外部也可以訪問(wèn)到錯(cuò)誤對(duì)象倔幼。IE9修復(fù)了這個(gè)問(wèn)題。
沒(méi)有塊級(jí)作用域
聲明變量
使用var聲明的變量會(huì)自動(dòng)被添加到最接近的環(huán)境中爽待。在函數(shù)內(nèi)部损同,最接近的環(huán)境就是函數(shù)的局部環(huán)境。如果初始化變量時(shí)沒(méi)有使用var聲明鸟款,該變量會(huì)自動(dòng)添加到全局環(huán)境膏燃。
在嚴(yán)格模式下,初始化未經(jīng)聲明的變量會(huì)導(dǎo)致錯(cuò)誤何什。
查詢標(biāo)識(shí)符
垃圾收集
JavaScript具有自動(dòng)垃圾回收機(jī)制组哩,執(zhí)行環(huán)境會(huì)負(fù)責(zé)管理代碼執(zhí)行過(guò)程中使用的內(nèi)存。
垃圾收集器必須跟蹤哪個(gè)變量有用哪個(gè)變量沒(méi)用,對(duì)于不在有用的變量打上標(biāo)記伶贰,以備將來(lái)收回其占用的內(nèi)存蛛砰。用于標(biāo)識(shí)無(wú)用變量的策略可能會(huì)因?qū)崿F(xiàn)而異,但具體到瀏覽器中的實(shí)現(xiàn)黍衙,則通常有兩個(gè)策略泥畅。
標(biāo)記清除
JavaScript中常用的垃圾收集方式是標(biāo)記清除(mark-and-sweep)。