JS變量松散類型的本質(zhì),決定了它只是在特定時間用于保存特定值的一個名字而已
4.1 基本類型和引用類型的值
基本類型:按值傳遞
引用類型:JS不允許直接操作對象的內(nèi)存空間薇正,所以引用類型是按引用訪問的
4.1.1 復(fù)制變量值
基本類型:num2中的5和num1中的5是完全獨立的
var num1 = 5;
var num2 = num1;
num1 = 6;
num1 ==> 6
num2 ==> 5
引用類型:兩個變量實際上引用同一個對象柑晒,改變其中一個欧瘪,就會影響另一個;
var obj1 = {};
var obj2 = obj1;
obj1.name = 'jack';
obj2.name ==> 'jack'
4.1.2 傳遞參數(shù)
訪問變量有按值和按引用兩種方式匙赞,而所有函數(shù)的參數(shù)都是按值傳遞
function addTen(num){
num += 10;
return num
}
var count = 20;
var result = addTen(count);
count ==> 20 // 沒有變化
result ==> 30
使用對象傳參
function setName(obj){
obj.name = 'www'
}
var person = new Object();
setName(person);
person.name ==> 'www'
在這個函數(shù)內(nèi)部佛掖,obj和person引用的是用一個對象
function setName(obj){
obj.name = 'wwww';
obj = {};
obj.name = 'greg';
}
var person = {};
setName(person);
person.name ==> 'www'
即使在函數(shù)內(nèi)部修改了參數(shù)的值,但原始的引用仍然保持不變涌庭。當(dāng)在函數(shù)內(nèi)部重寫了obj時芥被,
這個變量引用的就是一個局部對象了,這個局部對象
會在函數(shù)執(zhí)行完畢后立即被銷毀坐榆;
所有的這些都說明拴魄,函數(shù)參數(shù)是按值傳遞的,函數(shù)的參數(shù)一定程度上說是局部變量猛拴;
4.1.3 檢測類型
檢測字符串羹铅,數(shù)值蚀狰,布爾愉昆,undefined,用typeof
typeof檢測引用類型值都返回Object
typeof null ==> 'object';
使用typeof 檢測undefined會出現(xiàn)一個問題:
var name;
var sex = undefined;
typeof name ==> undefined //檢測定義了未賦值變量name為undefined
typeof age ==> //檢測未定義變量age 麻蹋,返回undefined
typeof sex ==> //檢測值為undefined的變量sex跛溉,返回undefined
這個可能會造成一些混亂,所以確保只有未定義時扮授,才返回undefined芳室。其他兩種情況,請盡量避免刹勃。
檢測引用類型:instanceof
var arr = [];
arr instanceof Array ==> true
使用instanceof檢測基本類型堪侯,則始終會返回false,因為基本類型不是對象
4.2 執(zhí)行環(huán)境和作用域
執(zhí)行環(huán)境:定義了變量或函數(shù)有權(quán)訪問的其他數(shù)據(jù)荔仁,決定了他們各自的行為伍宦;
局部環(huán)境在執(zhí)行完畢后芽死,其中的變量和函數(shù)定義也會被銷毀
全局環(huán)境在應(yīng)用程序退出,關(guān)閉網(wǎng)頁或退出瀏覽器時次洼,其中的變量和函數(shù)定義會被銷毀
每個函數(shù)都有自己的執(zhí)行環(huán)境关贵。當(dāng)執(zhí)行流進入到一個函數(shù)中時,
函數(shù)的環(huán)境會被推入一個環(huán)境棧中卖毁,而在函數(shù)執(zhí)行之后揖曾,棧將其環(huán)境彈出,把控制權(quán)還給之前的執(zhí)行環(huán)境亥啦。
每個環(huán)境都可以向上搜索作用域鏈炭剪,以查詢變量和函數(shù)名,但任何環(huán)境都不能通過向下搜索作用域鏈而進入另一個執(zhí)行環(huán)境
4.2.1 延長作用域鏈
try-catch
with語句
4.2.2 沒有塊級作用域
if(true) {
var color = 'blue'
}
alert(color) ==> 'blue'
由于不存在塊級作用域翔脱,所以if語句的變量聲明會將變量添加到當(dāng)前的執(zhí)行環(huán)境(這里是全局環(huán)境)
for (var i = 0; i < 10; i ++) {
doSomething(i)
}
alert(i) ==> 10
由于不存在塊級作用域念祭,由for語句創(chuàng)建的變量i即使在for循環(huán)執(zhí)行結(jié)束后,
也依舊會存在于循環(huán)外部的執(zhí)行環(huán)境中
1. 聲明變量
使用var聲明的變量會自動被添加到最接近的環(huán)境中碍侦,在函數(shù)內(nèi)部叫潦,
最接近的環(huán)境就是函數(shù)的局部環(huán)境途戒,未經(jīng)var聲明過的變量,會被自動添加到全局環(huán)境中,
4.3 垃圾收集
javascript具有自動垃圾收集機制笨腥,執(zhí)行環(huán)境會負(fù)責(zé)管理代碼執(zhí)行過程中使用的內(nèi)存,所需內(nèi)存的分配以及無用內(nèi)存的回收完全實現(xiàn)了自動管理娜庇。
這種垃圾收集機制原理:找出那些不再繼續(xù)使用的變量炫贤,然后釋放其占用的內(nèi)存;
怎么樣找到哪些變量將不再被繼續(xù)使用尔邓?
垃圾收集器必須跟蹤哪個變量有用哪個沒有用晾剖,對于不再有用的變量打上標(biāo)記,以備將來收回其占用的內(nèi)存梯嗽;
用于標(biāo)示無用變量的兩個策略:
4.3.1 標(biāo)記清除:
在變量進入環(huán)境和離開環(huán)境時齿尽,分別為其添加標(biāo)記,清除離開的變量灯节,釋放內(nèi)存循头;
4.3.2 引用計數(shù)(不太常用)
4.3.3 性能問題
4.3.4 管理內(nèi)存
js在進行內(nèi)存管理和垃圾收集時面臨一個問題,js分配給web瀏覽器的可用內(nèi)存數(shù)量通常要比分配給桌面應(yīng)用的少炎疆,這樣做是出于安全考慮卡骂,防止運行js的網(wǎng)頁耗盡全部系統(tǒng)系統(tǒng)內(nèi)存而導(dǎo)致系統(tǒng)崩潰,因此形入,確保占用最少內(nèi)存可以讓頁面獲得更好的性能全跨;
優(yōu)化內(nèi)存最佳方式,就是為執(zhí)行中的代碼只保存必要的數(shù)據(jù)亿遂,一旦數(shù)據(jù)不再有用浓若,
最好通過將其設(shè)置為null來釋放其引用盒使,這個方法叫做解除引用,這一做法
適用于大多數(shù)全局變量和全局對象的引用七嫌,因為局部變量會在它們離開執(zhí)行環(huán)境時自動被解除引用少办;
如下例:
function createPerson(name){
var localPerson = new Object();
localPerson.name = name;
return localPerson;
}
var globalPerson = createPerson('wang');
//手工解除globalPerson的引用
globalPerson = null;
解除引用的真正目的是讓值脫離執(zhí)行環(huán)境,以便垃圾收集器下次運行時將其回收诵原;