紀錄目前為止個人覺得蠻重要的javascript特性和觀念:
以下程式碼,你能看出console的輸出結果嗎?
1、
var var1 = 'a';
function fun1 (var1) {
var1='b';
console.log(var1);
}
fun1(var1);
console.log(var1);
2、
var var2 = {
proper: 'a'
};
function fun2(var2) {
var2.proper = 'b';
console.log(var2.proper);
var var3 = var2;
console.log(var3.proper);
}
fun2(var2);
console.log(var2.proper);
console.log(var3.proper);
3、
var var4 = {
proper1: 'a'
};
function fun3(var4) {
var4 = {
proper1: 'b',
proper2: 'w'
};
console.log(var4.proper1);
console.log(var4.proper2);
}
fun3(var4);
console.log(var4.proper1);
console.log(var4.proper2);
4、
var var5 = {
proper1: 'a',
proper2: {}
};
function fun4(){
var var6 = var5,
proper1 = var6.proper1,
proper2 = var6.proper2;
proper1 = 'b';
console.log(var6.proper1);
proper2.attr = 'w';
proper2 = 'y';
console.log(typeof var6.proper2);
console.log(var6.proper2.attr);
var obj = {
properx: 'z'
};
var6.proper2.z = obj;
console.log(var6.proper2.z.properx);
return var6;
}
var var7 = fun4();
console.log(var5.proper1);
console.log(var5.proper2.attr);
var5 = '';
console.log(var7.proper2.attr);
console.log(var7.proper2.z);
console.log(var7.proper2.z.properx);
以下解答:
1、
var var1 = 'a';
function fun1 (var1) {
var1='b';
console.log(var1);
}
fun1(var1); //呼叫fun1並傳入global 變數var1的值(基本形態的字串'a')存入local變數var1之中,於fun1中修改了local變數var1的值為字串的'b',緊接著在console輸出local變數var1的值 'b'
console.log(var1);//輸出global變數var1的值'a'
//程式碼1執行結果驗證
2、
var var2 = {
proper: 'a'
};
function fun2(var2) {
var2.proper = 'b';
console.log(var2.proper);
var var3 = var2;
console.log(var3.proper);
}
fun2(var2);//呼叫fun2並傳入global變數var2的值(global物件形態指標),存入local變數var2,在函數內部對global物件的proper屬性值做修改,改為'b',接著console輸出這個屬性的值'b',接著宣告一個local變數var3,並將local var2的值(global 物件指標)賦於var3,接著console輸出global物件的proper屬性值'b'
console.log(var2.proper);//console輸出global var2的值(global物件)的proper屬性值'b'
console.log(var3.proper);//因scope限制,無法存取local變數var3的值(global物件的指標),於console輸出var3 is not defined,也就無法進一步讀取物件的proper屬性值
//程式碼2執行結果驗證
3、
var var4 = {
proper1: 'a'
};
function fun3(var4) {
var4 = {
proper1: 'b',
proper2: 'w'
};
console.log(var4.proper1);
console.log(var4.proper2);
}
fun3(var4);//呼叫fun3並傳入global變數var4的值(物件形態指標)存入local變數var4中,於函數內部對local變數var4做賦新值的動作,宣告一個local的物件存入其中,覆蓋掉原本的global物件指標,新物件擁有兩個屬性,接著console輸出local物件的兩個屬性值,分別為'b'和'w'
console.log(var4.proper1);//console輸出global物件的proper1屬性值'a'
console.log(var4.proper2);//global物件未定義proper2這個屬性,console輸出undefined
//程式碼3執行結果驗證
4、
var var5 = {
proper1: 'a',
proper2: {}
};
function fun4(){
var var6 = var5,
proper1 = var6.proper1,
proper2 = var6.proper2;
proper1 = 'b';
console.log(var6.proper1);
proper2.attr = 'w';
proper2 = 'y';
console.log(typeof var6.proper2);
console.log(var6.proper2.attr);
var obj = {
properx: 'z'
};
var6.proper2.z = obj;
console.log(var6.proper2.z.properx);
return var6;
}
var var7 = fun4();//呼叫func4,於函數內宣告local變數var6,並將global變數var5的值(global物件指標)賦於它,接著宣告兩個local變數proper1, proper2並分別將global物件的proper1屬性的值('a')與proper2屬性的值(global物件指標)賦予兩者,
接著修改local變數proper1的值為文字'b',接著console輸出global物件的proper1屬性值'a',接著為置於local變數proper2中的global物件新增一個名為attr的屬性,並賦予其值為文字'w',接著修改local變數proper2的值為文字'y',覆蓋掉原本的global物件指標,
接著console輸出置於local變數var6中的global物件的proper2屬性之形態,結果為object,然後接著console輸出其attr屬性值'w',接著宣告一個local變數obj,賦於其一個local物件,此物件擁有一個properx屬性,值為文字'z',接著為global物件的proper2屬性值(global物件指標),新增一個屬性名為z,並將local變數obj的值(local物件指標)賦予它,
然後console輸出置於global物件中的global屬性變數z中的local物件之properx屬性值'z',最後回傳local變數var6的值(與global變數var5相同的global物件指標)存於global變數var7中
console.log(var5.proper1);//console輸出置於global變數var5中的global物件的proper1屬性值'a'
console.log(var5.proper2.attr);//console輸出global物件的proper2屬性值(物件指標)的attr屬性值'w'
var5 = '';//修改global變數var5的值為''
console.log(var7.proper2.attr);//console輸出global變數var7的值(global物件指標,此時var5已解除與此物件的reference)的proper2屬性值(物件指標)的attr屬性值'w'
寫到這邊忽然領悟到{}物件形態是指標,無scope限制,文中'global物件'以及'local物件'之修詞並不恰當,應統一稱'物件形態指標'
console.log(var7.proper2.z);//因scope限制,無法存取z屬性中儲存的local物件,console輸出undefined => 更正,物件形態指標不受scope影響,console輸出Object {properx: "z"}
console.log(var7.proper2.z.properx);//因上列原因,無法進一步存取local物件的properx屬性,console輸出undefined => 更正,物件形態指標不受scope影響,console輸出屬性值'z'
//程式碼4執行結果驗證
記憶體管理:
未被任何變數參照的記憶體會被GC回收,然後釋放記憶體(滿足特定條件時,不一定即時)
var ref1 = {
proper1: 'abc'
};//ref1參照到此物件
var ref2 = ref1;//現在ref2也參照到該物件,該物件被兩個變數參照
ref1 = '';//ref1不再參照到該物件,剩ref2參照
ref2 = '';//現在物件{proper1: 'abc'}已無任何變數參照,將會被GC回收釋放記憶體
更詳細的解說可參考下列連結文章:
簡單理解 JavaScript 的記憶體管理機制
刪除變數使用delete關鍵字
沒有留言:
張貼留言