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的地址,父执行环境的活动对象不会被销毁。还在内存中。 此链一直包含父执行环境的活动对象。
时间: 2024-10-03 23:54:01

js执行环境的深入理解的相关文章

JS 执行环境与作用域链

1.执行环境 JavaScript 代码都是在执行环境中被执行的.执行环境是一个概念,一种机制,用来完成JavaScript运行时在作用域.生命周期等方面的处理,它定义了变量或函数是否有权访问其他数据,决定各自行为.每个执行环境都有一个变量对象(我理解为环境变量对象),在代码执行环境中所有的变量.函数都保存在这个对象中: 全局的执行环境是最外围的执行环境,根据ECMAScript 实现所在的宿主环境同,表示执行环境的对象也不一样,在WEB浏览器中,全局执行环境被认为是Windows对象,因此所有

浅谈JS执行环境及作用域

 今天刚刚开通博客,也是第一次写博文,略感紧张.作为一个表达能力弱弱的人来说,自己花三分钟理解一个知识点,当别人问起时,也许需要30分钟才只是让别人知道自己在说什么,一点也不夸张,希望在博客上可以练习对语言的组织能力并记录学习笔记与大家一起交流. 进入正题>> 首先,相关的概念定义如下: 1. 执行环境: 所有 JavaScript 代码都是在一个执行环境中被执行的.执行环境是一个概念,一种机制,用来完成JavaScript运行时在作用域.生存期等方面的处理,它定义了变量或函数有权访问的其他数

对执行环境的深刻理解

这2处的代码是高级程序第三版的代码.个人觉得高三解释的不是很深入没有解释清楚.所以我按照ECMA从新解释了下. function createFunctions(){var result = new Array();for (var i=0; i < 10; i++){result[i] = function(num){//创建函数时创建包含所有父执行环境的变量对象作用域链,第一次进入函数的执行环境,活动对象里的num属性值为0:第二次进入函数的执行环境,每次进入的函数的执行环境都是一个新的执行

预备JS执行环境,预执行脚本

page.evaluateOnNewDocument(pageFunction, ...args) pageFunction <function|string> Function to be evaluated in browser context ...args <...Serializable> Arguments to pass to pageFunction returns: <Promise> Adds a function which would be in

javascript 作用域链及闭包,AO,VO,执行环境

下面的文章内容会根据理解程度不断修正. js变量作用域: 定义:变量在它申明的函数体以及函数体内嵌套的任意函数体内有定义. function AA(){ var bb='我是AA内部变量'; function TT(){ alert(bb); } alert(bb); TT(); } AA(); 如上图,两次弹出的都是“我是AA内部变量”. JS的变量作用域是函数级的,也就是在AA内部申明的变量,在AA内部任意位置,包括它嵌套的函数内也是有定义的. 在函数AA外面,bb就是没有定义的.当然如果去

Chrome扩展修改页面代码执行环境的方法

Chrome的扩展程序可以通过content scripts向页面中注入js代码,所注入的js代码能够对页面中所有的DOM对象进行操作.由于Chrome在js执行环境上对页面代码和content scripts代码进行了隔离,所以,在content scripts中,无法直接修改页面代码执行环境.不过我们还是可以通过一些技巧向页面代码执行环境中插入想要执行的js代码段,从而能够修改页面代码的执行环境. 第一种方法,通过在DOM对象上添加一个event handler,然后派发对应的event给该

js对象字面量属性间相互访问的问题 和 这个问题与执行环境的关系

对象字面量属性间无法相互访问的问题: 我曾经在定义一个对象时, 并出于复用性的考虑试图复用某些属性: // test 1 var person = { firstName : "Bill", lastName : "Gates", fullName : firstName + " " + lastName // 这里报错 } alert(person.firstName); alert(person.lastName); alert(person

js函数绑定同时,如何保留代码执行环境?

经常写js的程序员一定不会对下面这段代码感到陌生. 1 var EventUtil = { 2 3 addHandler : function(element, type, handler){ 4 if(element.addEventListener){ 5 element.addEventListener(type, handler, false); 6 }else if(element.attachEvent){ 7 element.attachEvent("on"+type,h

js一个关于作用域和执行环境的例子

在网上无意中看到一个关于js的作用域和执行环境的面试题,以前我也没怎么总是这些东西,经过一小段时间的研究,我慢慢开始明白其中的奥妙,这对以后写程序还是大有帮助的.日志代码如下: f = function() {return true;};  g = function() {return false;};  (function() {     if (g() && [] == ![]) {        f = function f() {return false;};        fun