第一个例子中 :之所以每个函数都返回不同的值的原因 有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的地址,父执行环境的活动对象不会被销毁。还在内存中。 此链一直包含父执行环境的活动对象。

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

  1. js执行环境、作用域

    js执行环境.作用域 执行环境:是javascript中的一个重要的概念,<javascript高级程序设计第三版>的定义是:执行环境定义了变量或函数有权访问的其他数据,决定了他们各自的行 ...

  2. 【repost】 原生JS执行环境与作用域深入理解

    首先,我们要知道执行环境和作用域是两个完全不同的概念. 函数的每次调用都有与之紧密相关的作用域和执行环境.从根本上来说,作用域是基于函数的,而执行环境是基于对象的(例如:全局执行环境即window对象 ...

  3. JS 执行环境与作用域链

    1.执行环境 JavaScript 代码都是在执行环境中被执行的.执行环境是一个概念,一种机制,用来完成JavaScript运行时在作用域.生命周期等方面的处理,它定义了变量或函数是否有权访问其他数据 ...

  4. js执行环境相关

    Js执行过程 如果一个文档中存在多个代码段 步骤一:读入第一个代码段(js引擎并非一行一行执行,而是一段一段分析执行) 步骤二:做词法分析和语法分析,有错则报语法错误(比如括号不匹配等),并跳转到步骤 ...

  5. JS执行环境,作用域链及非块状作用域

    JS中的执行环境,顾名思义就是变量或函数所执行时的环境.在我的理解中,执行环境和作用域相差不大. 每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中.而在函数执行之后 ...

  6. 浅谈JS执行环境及作用域

     今天刚刚开通博客,也是第一次写博文,略感紧张.作为一个表达能力弱弱的人来说,自己花三分钟理解一个知识点,当别人问起时,也许需要30分钟才只是让别人知道自己在说什么,一点也不夸张,希望在博客上可以练习 ...

  7. js执行环境深入研究

    js 声明函数是创建函数对象的过程,当创建函数对象时,函数对象的[[scope]] =连当前执行环境对象的作用域(栈顶执行环境--当执行函数时,js会将该函数的执行环境对象入栈) 当为全局函数时,如: ...

  8. js执行环境的周边概念

    一.熟悉几个名词: 1.执行环境(execution context),也叫执行上下文,每个函数都会有自己的执行环境:当浏览器首次加载脚本时,他将默认进入全局执行环境:如果接下来要调用一个内部函数,则 ...

  9. JS执行环境栈及事件循环机制—简洁明了的讲解

    JavaScript解释器在浏览器中是单线程的,这意味着浏览器在同一时间内只执行一个事件,对于其他的事件我们把它们排队在一个称为 执行栈(调用栈) 的地方.下表是一个单线程栈的抽象视图: 我们已经知道 ...

随机推荐

  1. 【BZOJ】3922: Karin的弹幕

    题意 给定一个长度为\(n(1 \le n \le 70000)\)序列,\(m(1 \le m \le 70000)\)次操作:1. 对一段下标是等差数列的子序列求最大值:2. 单点修改. 分析 如 ...

  2. JS:call()和apply的区别

    每个函数都包含两个非继承而来的方法:call()和apply(); call()方法:参数,第一个是作用域中调用函数(this),其余是参数直接传给函数 扩大作用域,传递参数时,参数必须逐个列出. w ...

  3. 【JAVA】FOR UPDATE 和 FOR UPDATE NOWAIT 区别 (转)

    1.for update 和 for update nowait 的区别:首先一点,如果只是select 的话,Oracle是不会加任何锁的,也就是Oracle对 select 读到的数据不会有任何限 ...

  4. GridView的七种数据绑定列的类型

    1.BoundField 用于显示普通文本,是默认的数据绑定列的类型,一般自动生成的列就是该类型,需要注意是DataFormatString属性,该属性可以设置显示的格式,常见格式有:{0:C} 设置 ...

  5. JAVA面试题1

    1.在main(String[] args)方法内是否可以调用一个非静态方法? 答案:不能[public static void main(String[] args){}] 2.同一个文件里是否可以 ...

  6. Tickets——H

    H. Tickets Jesus, what a great movie! Thousands of people are rushing to the cinema. However, this i ...

  7. [转]基于Starling移动项目开发准备工作

    最近自己趁业余时间做的flash小游戏已经开发得差不多了,准备再完善下ui及数值后,投放到国外flash游戏站.期间也萌生想法,想把游戏拓展到手机平台.这两天尝试了下,除去要接入ane接口的工作,小游 ...

  8. 指针与数组的区别 —— 《C语言深度剖析》读书心得

    原书很多已经写的很清楚很精炼了,我也无谓做无意义的搬运,仅把一些基础和一些我自己以前容易搞混的地方写一下. 1. 意义: 指针: 指针也是一种类型,长度为4字节,其存放的内容只能是一个地址(4字节). ...

  9. *HDU1455 DFS剪枝

    Sticks Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  10. PHP入门介绍与环境配置

    浏览目录: 一.PHP的背景和优势: 二.PHP原理简介: 三.PHP运行环境配置: 四.编写简单的PHP代码以及测试. 一.PHP的背景和优势 1.1   什么是PHP? PHP是能让你生成动态网页 ...