文章部分实例和内容来自鸟哥的blogJavascript作用域原理

首先应该注意几个点:

  • 函数也是对象

  • variable object(VO)

A variable object is a container of data associated with the execution context. It’s a special object that stores variables and function declarations defined in the context.

    var foo=10;function func(){};//因为是在全局作用域当中,so...Global VO={foo:10,func:<function>}
  • Activation Object(AO)

  • When a function is activated (called) by the caller, a special object, called an activation object is created.

  • It’s filled with formal parameters and the special arguments object (which is a map of formal parameters but with index-properties). The activation object then is used as a variable object of the function context.

  • A function’s variable object is the same simple variable object, but besides variables and function declarations, it also stores formal parameters and arguments object and called the activation object.

    function foo(x,y){var z=30;function bar(){};}foo(10,20);//当执行到foo(10,20)时即会产生AOActivation Object={z:30,x:10,y:20,bar:<function>,arguments:{0:10,1:20,length:2}}
  • Scope Chain(Scope Chain=Activation Object + [[scope]])

A scope chain is a list of objects that are searched for identifiers appear in the code of the context.

  • 在JavaScript当中,函数的运行是在它被定义的作用域当中,而非执行的作用域当中。

先看一段代码:

    var name="laurence?";function show(){console.log(name);var name="laurence?";console.log(name);}最后输出: undefined  laurence?Object={name1:undefined,//第一个输出为undefined,表达式声明的局部变量覆盖全局变量,函数执行到这一语句的时候才进行赋值操作name="laurence?",之前name=undefinedname2:"laurence?",//第二个输出为"laurence?"
}
window={name:"laurence?",show:function()
}

注意点:

  • 函数也是对象

  • 变量提升

  • 函数在定义过程中,会将定义时刻的scope chain链接到这个函数对象的[[scope]]属性上,这个属性包含了函数被创建的作用域中 对象 的集合,同时它的作用域会被创建此函数的作用域中可访问的数据对象填充。(对象的集合、对象链)

  • 函数的执行过程中,会创建一个 活动对象 (activation object),该对象包含了所有的局部变量命名参数参数集合this,然后将这个活动对象作为此时作用域链的最前端,每个活动对象都有自己的作用域链,用于标识符的解析,当活动对象被创建时,而它的作用域初始化为当前运行函数的[[scope]]所包含的对象。

var func=function(lps,rps){var name="XL";....
}
func();
  • var func=function(){ } 相当于匿名函数的执行

  • (在执行函数创建活动对象(Obj)的过程中,会创建一个arguments属性,然后会给这个活动对象添加2个属性名,Obj.lps,Obj.rps对于每一个在这个函数中申明的局部变量和函数定义,都作为该活动对象的同名属性,然后将调用参数赋值给形参,对于缺少的调用参数,赋值为undefined)

//这里func()执行时
Obj(AO)={lps:undefined,rps:undefined,arguments:{}name:"XL"
}
//创建func()时为全局对象:
window(Global VO)={func:function()
}

实际的例子:

function factory(){var name="laruence";var intro=function(){console.log("I'm "+name);}return intro;
}
function app(para){var name=para;var func=factory();func();
}app("eve");

当调用app的时候,scope chain是由{window活动对象(全局)}+{app活动对象}组成

此时的[[scope chain]]为( 可访问的数据对象访问 ):

[[scope chain]]=[
Active Object={this:window,arguments:{0:"eve",length:1}name:'eve'func:<function>para:"eve",
},
Global VO={this:window,app:<function>,window:<object>,document:<object>
}
]

当调用进入factory函数体内时(注意这里,函数的scope chain是在它被定义的时候决定的,而非执行的时候决定的),此时的factory的scope chain为:

[[scope chain]]={
Active Object={this:window,arguments:{},name:"laruence",intro:<function>,
},
Global Object(Variable Object)={this:window,factory:<function>,app:<function>,window:<object>,document:<object>
}
}

在定义intro函数的时候,intro函数[[scope]]为:

[[scope chain]]={
Object={name:"laruence",intro:<function>,this:<factory>,     //注意这里的this指向arguments:{}
},
Gloabal Object={this:window,factory:<function>,document:<object>,window:<object>
}
}

factory函数返回后,在app体内调用intro时,发生了标识符的解析,而此时的scope chain是:

[[scope chain]]={intro AO={<intro 活动对象>} ,Factory AO={name:"laruence",intro:<function>,},Global VO={this:window,factory:<function>,document:<obeject>,window:<object>}
}

在intro执行过程中scope chain不包含app活动对象,因此name标识符解析的结果应该是factory活动对象中的name属性,也就是"laruence"

预编译

JS在执行每段代码前都会首先处理var关键字( 函数定义式 )和function定义式( 函数声明式 )

变量提升(hoisting)

1.javascript-the-core(强烈推荐)
2.理解javascript作用域和作用域链

javascript作用域链详解相关推荐

  1. JavaScript作用域和作用域链详解

    JavaScript作用域链详解 一.JavaScript作用域 JavaScript作用域是什么? 作用域范围 二.JavaScript作用域链 作用域与执行上下文 总结 一.JavaScript作 ...

  2. Js作用域与作用域链详解

    一直对Js的作用域有点迷糊,今天偶然读到Javascript权威指南,立马被吸引住了,写的真不错.我看的是第六版本,相当的厚,大概1000多页,Js博大精深,要熟悉精通需要大毅力大功夫. 一:函数作用 ...

  3. 作用域和作用域链详解

    1. *****作用域和作用域链 作用域scope:       什么是: 一个变量的使用范围--使用                  本质上作用域是一个对象--存储                 ...

  4. javaScript原型链详解

    首先我们要清楚地知道原型链的本质:原型链是一种关系,实例对象和原型对象之间的关系. 接下来就来细细分析,我们先看一段代码: 这里定义了一个构造函数Person(),然后创建了两个实例对象per,per ...

  5. javaScript函数模块详解

    javaScript函数模块详解 ​ 函数实际上是对象,每个函数都是Function类型的实例,而Function也有属性和方法,和其他引用类型一样 可以将函数名想象成指针,函数想象成对象 ​ 注意, ...

  6. javascript BOM对象详解

    javascript BOM对象详解 目标:本章节将分为9点详细介绍有关BOM对象的知识点 1.什么是BOM 2.BOM的构成 3.顶级对象window 4.window对象常见事件(页面加载事件和体 ...

  7. JavaScript Class类详解

    ECMAScript 6 提供了更接近传统语言的写法,新引入的class关键字具有正式定义类的能力.类(class)是ECMAScript中新的基础性语法糖结构,虽然ECMAScript 6类表面上看 ...

  8. Token 防盗链详解

    前言 随着互联网的高速发展,无论是移动 APP 还是 WEB 站点,访问的安全问题始终困扰着内容提供商.CDN ( Content Delivery Network,内容分发网络 ) 服务作为当今互联 ...

  9. 对javascript作用域链的理解

    这几天学习了一下javascript作用域链,感到这个挺重要的,所以写一篇文章分享一下: 1. 作用域链: 当代码在一个环境中执行时,会创建由变量对象构成的一个作用域链.作用域链的用途是:保证对执行环 ...

  10. JavaScript 运行机制详解(理解同步、异步和事件循环)

    1.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊. Java ...

最新文章

  1. OpenCV(基础补充)图像二值化
  2. AJAX 实现form表单提交
  3. OpenVINO FPS也可以达100帧
  4. vim 使用技巧 转载
  5. 一站式金融云托管服务 都匀融通村镇银行系统成功上线运行
  6. python中@wraps的作用
  7. 怎么hold住版本质量
  8. 近期在做或要做的实验
  9. CPU中的Little Endian与Big Endian
  10. [转载] python numpy.random.randn()与numpy.random.rand()的区别 (正态分布公式)(标准正态分布 standard normal distribution
  11. android转iOS看什么书,一起聊聊:是什么让你从Android转向iOS?
  12. 林期苏曼属性标签编辑_标签制作软件如何制作商品标签模板
  13. SecureCRT SecureFx 绿色破解版
  14. 关于actel FPGA下载的学习报告
  15. 高级语言 和 低级语言 的区别
  16. Terminator zsh
  17. 大数据24小时:地质局发布地质大数据共享平台,科大讯飞将语音识别植入腾讯小Q机器人
  18. 搭建Android应用程序的服务器
  19. python3.7 统计某一只股票每天的开盘,收盘,最高,最低价格
  20. 史上最强的前端面试题!

热门文章

  1. Linux如何动态查看文件信息,怎么查看linux动态链接库文件的版本等其他信息
  2. sigmoid层的输出_keras如何多输入多输出,以及中间层输出
  3. vs2017远程编译linux教程,Visual Studio 2017 远程编译调试 Linux 上已存在的通过 Samba 共享的 CMake 工程...
  4. php创建游戏房间思路,php设计模式之建造器模式分析【星际争霸游戏案例】
  5. java分布式商城项目环境搭建1-CentOS7.6-安装JDK1.8
  6. linux内核阻塞IO
  7. Apache静态缓存配置
  8. Mysql 分组聚合实现 over partition by 功能
  9. zabbix监控系统的实际应用(客户端安装-基本应用设置-报警提醒篇)
  10. Struts2基础总结