第一个例子中 :之所以每个函数都返回不同的值的原因 有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. Dijkstra算法初步 - 迷宫问题

    你来到一个迷宫前.该迷宫由若干个房间组成,每个房间都有一个得分,第一次进入这个房间,你就可以得到这个分数.还有若干双向道路连结这些房间,你沿着这些道路从一个房间走到另外一个房间需要一些时间.游戏规定了 ...

  2. oracle 数据库 时间差 年数、月数、天数、小时数、分钟数、秒数

    declare l_start date := to_date('2015-04-29 01:02:03', 'yyyy-mm-dd hh24:mi:ss'); l_end date := to_da ...

  3. Hibernate学习笔记4

    一.关于联合主键的映射测试实例 实体类: package com.***.comBineKey;public class Person { private Person_pk pk; private ...

  4. Node.js实现CORS跨域资源共享

    什么是CORS CORS(Cross-origin resource sharing),跨域资源共享,是一份浏览器技术的规范,用来避开浏览器的同源策略 简单来说就是解决跨域问题的除了jsonp外的另一 ...

  5. mallmold开源商城系统网银在线chinabank支付插件

    最近没事捣鼓项目,找了个轻型商城系统mallmold,用起来还觉的挺不错的,尤其是mallmold中文版,赞一个.中文版集成了大部分主流支付系统,但因是个人网站,没法获得对应的服务,最终选择了网银在线 ...

  6. mysql刷日志的两个参数

    innodb_flush_log_at_trx_commit 0:每秒 ----log---disk1:事物提交 ---log ---disk2:事物提交---log 每秒 ---disk sync_ ...

  7. 几款不错的VisualStudio2010插件

    1.Gradient Selection 这个插件能使VisualStudio的高亮文本看起来是类似Blend的那样的效果,看起来更加舒服 2.LineAdornments 这个插件可以高亮光标所在的 ...

  8. MySQL优化性能my.cnf详解

    提供一个MySQL 5.6版本适合在1GB内存VPS上的my.cnf配置文件(点击这里下载文件): [client] port=3306 socket=/tmp/mysql.sock [mysqld] ...

  9. SqlServer 笔记一 某表中每个月的产品数量(DATENAME() 与 DATEPART()、YEAR())

    1.使用 DATENAME() 函数 SELECT DATENAME(yyyy, [columnName]) + '/' + DATENAME(mm, [columnName]) AS monthDa ...

  10. PHP之简单实现MVC框架

    PHP之简单实现MVC框架   1.概述 MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种 ...