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的地址,父执行环境的活动对象不会被销毁。还在内存中。 此链一直包含父执行环境的活动对象。
相关文章
相关标签/搜索