js執行環境的深刻理解

第一個例子中 :之因此每一個函數都返回不一樣的值的緣由 有2點 (簡寫以下文)

就是[SCOPE]內部屬性,函數可能擁有相同的父做用域時,多個函數引用同一個[SCOPE]屬性,因此return i的值仍是10(第一點),可是return num的值就不是了。由於每一個內部函數的父執行環境都是新的(由於每次I++以後函數都會被調用執行每次進入的環境是新的)。因此多個函數不引用同一個[scope]屬性,建立函數時[scope]中的做用域鏈中的全部父執行環境的A0/VO都是一個新的。固然全局父執行環境不是。由於它只被進入一次。(第二點)

function createFunctions(){
var result = new Array();
for (var i=0; i < 10; i++){
result[i] = function(num){//建立函數時建立包含全部父執行環境的V0/AO對象指針做用域鏈,此鏈被保存在建立的函數的內部屬性[[Scope]]中,第一次進入函數的執行環境,活動對象裏的num屬性值爲0;第二次進入函數的執行環境,每次進入的函數的執行環境都是一個新的執行環境。很明顯兩次的執行環境是不一樣的。因此,此時活動裏的num屬性值爲1;

return function(){//建立函數時建立包含全部父執行環境的V0/AO對象指針做用域鏈,此鏈被保存在建立的函數的內部屬性[[Scope]]中,此時的num爲0;當進入 result[0]()函數的執行環境時他的做用域鏈的第二個活動對象指針是父函數執行環境的活動對象 值爲0;當進入 result[1]()第二次進入函數的新執行環境時,做用域鏈的第二個活動對象指針是父函數執行環境的活動對象,注意:此時的父函數的執行環境是一個新的執行環境,因此它的做用域鏈的第二個活動對象指針指向新的父函數執行環境的活動對象;還有一點當return函數退出時,父執行環境被銷燬,可是活動對象依然保存在內存中(由於內部閉包匿名被引用中。);每一個被保存到result數組裏面的函數的執行環境的做用域鏈的第二個活動對象指針引用的都是一個新的父執行環境的活動對象;因此num值爲1;這裏之因此每一個函數都返回不一樣的值的緣由 有2點。一點是我以前說的一大堆,第二點就是[SCOPE]內部屬性,函數可能擁有相同的父做用域時,多個函數引用同一個[SCOPE]屬性,因此return i的值仍是10,可是return num的值就不是了。由於每一個內部函數的父執行環境都是新的。因此多個函數不引用同一個[scope]屬性 ,建立函數時[scope]中的做用域鏈中的全部父執行環境的A0/VO都是一個新的。固然全局父執行環境不是。由於它只被進入一次。

return num;
};
}(i);//當循環體執行完畢後。result[i]裏面的每一個函數對象都是不相等的。
}
return result;
}

 

此例子的緣由仍是由於父執行環境相同不相同的問題。
function createFunctions(){ // 
var result = new Array();
for (var i=0; i < 10; i++){
result[i] = function(){// 建立函數時建立包含全部父執行環境的V0/AO對象指針做用域鏈,此鏈被保存在建立的函數的內部屬性[[Scope]]中,
return i;
};
}
return result;//result[i]裏面的每一個函數對象都是不相等的。當循環體結束後createFunctions函數的執行環境的活動對象的屬性i=10;父函數執行環境只被進入一次。 result[i]()每次進入函數執行環境都是一個新的執行環境。全部函數的執行環境的做用域鏈中的全部父執行環境的VO/AO對象指針是複製建立函數時的[Scope]屬性中做用域鏈.循環語句中的多個函數可能擁有相同的父做用域時,多個函數引用同一個[SCOPE]屬性,而且此屬性中的做用域鏈的A0/VO是惟一的。由於父執行環境createFunctions只被進入一次,因此它的活動對象是惟一的.這就是爲何每一個函數都返回10的緣由;

}



function Person(name){
this.getName = function(){
return name;
};
this.setName = function (value) {
name = value;
};
}
var person = new Person("Nicholas");
alert(person.getName()); //"Nicholas"
person.setName("Greg");
alert(person.getName()); //"Greg"
var persoe = new Person("icholas");
alert(persoe.getName());//這裏彈出icholas是由於new的時候進入了新的函數的執行環境。而不是以前保存的執行環境 也就是說persoe.getName和person.getName的父執行環境不一樣。2個對象是不一樣的內存空間因此函數有2份。
alert(person.getName()); //"Greg" / /這裏之因此會彈出greg是由於進行執行環境時,他的scope屬性保存的做用域中的父執行環境中的VO對象指針是以前建立函數時的scope中的做用域鏈中的VO對象指針指向父執行環境中的VO對象。
說簡單點就是2個對象的方法的執行環境的做用域鏈中的第二個活動對象指針指向的是不一樣的父執行環境的活動對象。


總結:若是想要讓全部子執行環境引用同一個scpeo屬性,只須要讓父執行環境進入一次便可,這樣子執行環境就擁有相同的父執行環境了。此環境的的vo/AO是惟一的。既然是惟一的,那麼對此變VO/AO的屬性作的想修改會反應到全部子執行環境。


若是想要讓全部子執行環境引用不一樣的scpeo屬性,只須要讓父執行環境進入屢次便可,這樣子執行環境就不擁有相同的父執行環境了。不一樣的父執行環境的的vo/AO是不同的。;既然是不同的的,那麼對此VO/AO的屬性作的修改天然就反應到 和不一樣的執行環境相對應的子執行環境了。

還有一點就是:當父執行環境退出時,若是內部函數執行環境一直被引用狀態,那麼當再次進入此函數的執行環境時它的做用域鏈引用的是同一個SCOPE的地址,父執行環境的活動對象不會被銷燬。還在內存中。 此鏈一直包含父執行環境的活動對象。
相關文章
相關標籤/搜索