浅谈JS执行环境及作用域
今天刚刚开通博客,也是第一次写博文,略感紧张。作为一个表达能力弱弱的人来说,自己花三分钟理解一个知识点,当别人问起时,也许需要30分钟才只是让别人知道自己在说什么,一点也不夸张,希望在博客上可以练习对语言的组织能力并记录学习笔记与大家一起交流。
进入正题>>
首先,相关的概念定义如下:
1. 执行环境: 所有 JavaScript 代码都是在一个执行环境中被执行的。执行环境是一个概念,一种机制,用来完成JavaScript运行时在作用域、生存期等方面的处理,它定义了变量或函数有权访问的其他数据(包含了外部数据),决定他们各自的行为。包括以下分类:
全局执行环境: 全局环境是最外围的一个执行环境,根据ECMAScript实现所在的宿主环境不同,表示执行环境的对象也不一样,在web中,全局执行环境被认为是window对象。
函数执行环境: 每个函数都有自己的执行环境。
2. 变量对象: 每个执行环境都有一个变量对象与之关联,执行环境中定义的所有变量及函数(只包含在当前函数内定义的函数,局部变量)都保存在这个对象中,我们编写的代码无法直接访问这个对象,但解析器在处理数据时会在后台使用它。(参考下面的作用域,变量对象就是作用域为该执行环境的函数,变量的集合对象)
3. 作用域: 变量或方法有访问权限的代码空间,即变量或函数起作用的区域。(作用域包括全局作用域与函数作用域,没有块级块作用域,即一个变量的作用域不可能是一个块级域,至少包括最临近的整个函数空间。)
4. 作用域链: 由当前环境栈中对应的变量对象组成。作用域的用途,是保证对执行环境有权访问的所有变量和函数的有序访问,作用域前端,始终是当前执行的代码所在的环境对应的变量对象,下一变量对象来自包含(外部)环境,而再下一变量对象则来自下一包含环境,一直延续到全局执行环境。
以下分析将帮助大家理解上面的概念:
1. 执行环境与变量对象之间的对应关系
每个执行环境会有一个变量对象与之关联,该变量对象保存了执行环境中定义的所有局部变量及函数,变量对象具有动态性,只有在定义变量的语句得到执行才会将该变量添加到变量对象中,如下例中
function showA () {
consoloe.log(a); // 变量对象中没有保存a
alert(a);
}
2. 程序执行时,环境栈与执行环境的关系
当执行流进入一个函数时,即该函数正在执行,函数的执行环境就会被推入一个环境栈中,所有处在执行流的执行环境将有次序地保存在环境栈中,在函数执行之后,栈将其执行环境弹出,把控制权交给原来的执行环境。所以在程序执行中,环境栈是不断变化的,伴随着执行环境的出入,如下所示:
(摘自:笨蛋的座右铭的博文)
3. 理解环境栈,执行环境与作用域链之间的关系
在某一时刻,环境栈中保存的执行环境是一定的,以下面的程序为例,当fn2正在执行时
function Fn1() {
var a = 1;
function Fn2() {
var b = 2;
}
Fn2(); // 当程序执行到此时
}
Fn1();
此时环境栈状态如下:
此时环境栈包括:全局执行环境,fn1执行环境,fn2执行环境, 根据执行环境和变量对象具有的一一对应的关系,所以当前环境栈中执行环境和变量对象有以下对应关系
(摘自:笨蛋的座右铭的博文)
根据作用域链的定义,由右边的变量对象所组成的就是当前作用域链,链的前端为Fn2执行环境对应的变量对象
4. 作用域链的作用(标识符解析机制)
作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问(包括外部数据)
标识符解析是沿着作用域链一级一级地搜索标识符的过程,搜索始终从作用域链的前端开始,然后逐级地向后回溯,直到找到标识符为止。
示例1:
var color = 'blue';
functionshowColor () {
alert(color);
}
showColor(); // blue
在例1中,标识符解析从作用域链前端开始,顺着作用域链往后找,开始在showColor()的执行环境对应的变量对象中未能找到,之外在包含环境(全局执行环境)的变量对象中找到color变量,停止搜索,所以此时的color变量引用了全局中定义的color变量,于是输出为blue;
例2:
var color = 'blue';
function showColor () {
var color = 'red';
alert(color);
}
showColor(); // red
在例2中,标识符解析从作用域链前端开始,顺着作用域链往后找,在showColor()函数对应的执行环境对应的变量对象找到变量color,标识符解析程序立即停止搜索,此时color变量为函数中定义的color,于是输出为red
由以上两个例子中可以看出作用域链保证对执行环境有权访问的所有变量和函数的有序访问的原理:作用域链有序地保存了变量对象,由前向后,局部变量和函数往往保存在较前的变量对象中,因此被标识符解析的机会大于全局变量,也就有了局部变量会覆盖全局变量的现象,这样就保证了变量的有序访问。
5. 作用域与变量对象,执行环境的关系
由定义可知,作用域即函数或变量的作用区域。
变量或函数具有作用域的原因,就是在环境中定义的变量仅保存在了该执行环境对应的对象变量中,执行环境在环境栈中弹出之后,作用域链中找不到该对变量对象,以下面为例
function showColor () {
var color = 'red';
}
showColor(); // red
alert(color); // color is undefined
为什么在全局环境下showColor()内定义的变量不可访问呢,这是因为当函数执行到该语句时,color变量保存在了showColor()环境对应的变量对象中,现在showColor()已经执行完毕,该执行环境也从环境栈中弹出并销毁,所以此时的作用域链也不包括showColor()的执行环境对应的变量对象了,因为标识符解析是顺着作用域链查找变量的,所以这个过程不再能搜索到color变量,所以color变得只有定义该变量的函数中才能访问,具有一定范围的作用域。
以上内容为本人的理解,错误之处欢迎大家积极打脸~~
浅谈JS执行环境及作用域的更多相关文章
- js执行环境、作用域
js执行环境.作用域 执行环境:是javascript中的一个重要的概念,<javascript高级程序设计第三版>的定义是:执行环境定义了变量或函数有权访问的其他数据,决定了他们各自的行 ...
- JS执行环境,作用域链及非块状作用域
JS中的执行环境,顾名思义就是变量或函数所执行时的环境.在我的理解中,执行环境和作用域相差不大. 每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中.而在函数执行之后 ...
- 【repost】 原生JS执行环境与作用域深入理解
首先,我们要知道执行环境和作用域是两个完全不同的概念. 函数的每次调用都有与之紧密相关的作用域和执行环境.从根本上来说,作用域是基于函数的,而执行环境是基于对象的(例如:全局执行环境即window对象 ...
- JS 执行环境与作用域链
1.执行环境 JavaScript 代码都是在执行环境中被执行的.执行环境是一个概念,一种机制,用来完成JavaScript运行时在作用域.生命周期等方面的处理,它定义了变量或函数是否有权访问其他数据 ...
- 浅谈js执行机制
关于js执行机制,老早之前就一直想写篇文章做个总结,因为和js执行顺序的面试题碰到的特别多,每次碰到总是会去网上查,没有系统地总结,搞得每次碰到都是似懂非懂的感觉,这篇文章就系统的总结一下js执行机制 ...
- 【原】javascript执行环境及作用域
最近在重读<javascript高级程序设计3>,觉得应该写一些博客记录一下学习的一些知识,不然都忘光啦.今天要总结的是js执行环境和作用域. 首先来说一下执行环境 一.执行环境 书上概念 ...
- 浅谈 js eval作用域
原文:浅谈 js eval作用域 就简单聊下如何全局 eval 一个代码. var x = 1; (function () { eval('var x = 123;'); })(); console. ...
- 浅谈 js 正则字面量 与 new RegExp 执行效率
原文:浅谈 js 正则字面量 与 new RegExp 执行效率 前几天谈了正则匹配 js 字符串的问题:<js 正则学习小记之匹配字符串> 和 <js 正则学习小记之匹配字符串优化 ...
- js中的执行环境及作用域
最近在面试时被问到了对作用域链的理解,感觉当时回答的不是很好,今天就来说说js中的作用域链吧. 首先来说说js中的执行环境,所谓执行环境(有时也称环境)它是JavaScript中最为重要的一个概念.执 ...
随机推荐
- Tengine新增健康检查模块
总结 2.tengine的状态监控 Tengine的状态监控有两种 这里演示一个健康检查模块功能 配置一个status的location location /status { check_status ...
- [转]解决百度统计 gzdecode(): insufficient memory
百度统计API gzdecode($preLogin->retData, strlen($preLogin->retData)) 这段代码会造成一个PHP警告内存不足,解决办法只要换个解压 ...
- URAL 2045 Richness of words (回文子串,贪心)
Richness of words 题目链接: http://acm.hust.edu.cn/vjudge/contest/126823#problem/J Description For each ...
- HDU1398Square Coins(母函数)
母函数介绍见另一篇随笔HDU1028Ignatius and the Princess III(母函数) #include<iostream> #include<stdio.h> ...
- C语言经典算法100例(一)
C语言中有有许多经典的算法,这些算法都是许多人的智慧结晶,也是编程中常用的算法,这里面包含了众多算法思想,掌握这些算法,对于学习更高级的.更难的算法都会有很大的帮助,会为自己的算法学习打下坚实的基础. ...
- getopt使用例子
getopt是linux下获取程序启动参数的函数 #include <unistd.h> int getopt(int argc, char * const argv[], ...
- CKeditor3.6.2 配置与精简
一.使用方法: 1.在页面<head>中引入ckeditor核心文件ckeditor.js <script type="text/javascript" src= ...
- PostgreSQL的 initdb 源代码分析之一
开始第一段: int main(int argc, char *argv[]) { /* * options with no short version return a low integer, t ...
- 【OSG】osgText::Text 研究
由于需要在3D坐标轴上显示刻度值,所以要用到osgText::Text,这里简单记录一下其常见用法. 一.基本知识 常见设置 设置字体:setFont 设置内容:setText,这里输入参数需要是os ...
- Perl多进程
perl作为一种解释性的语言,非常受广大系统管理员的欢迎,优点么就不多说了,坏处也有不少,比如对线程的支持,就一直不咋地,所以大多数情况下,我们都须要多个进程,来帮助我们完毕工作,闲话少说,上代码. ...