javascript精雕细琢(三):作用域与作用域链
目录
- 引言
- 1、执行环境
- 2、作用域与作用域链
引言
作用域与作用域链是JS应用中无时无刻不在影响程序运行的关键属性,但是由于它的不可见性,或者说它存在的过于普遍,简直就像空气一样。所以对它的谈及,都很简单,而理解起来也不复杂。
但是由于它的重要性,对它做一个篇幅的说明,也是一件理所应当的事情。而且它其实也并没有理解上那么简单。
本文对作用域及作用域链的说明,可能并不全面。笔者尽量以自身开发过程中的理解,做到表述全面。
1、执行环境
按照《JavaScript高级程序设计》第3版中的定义——执行环境定义了变量或函数有权访问其他数据,决定了它们各自的行为。每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。
对于环境的简单理解,可以理解为{}一个大括号就是一个执行环境。如{{}},就是包含关系的两个执行环境。而由于所有的函数和变量,最终都是通过最外围有对应的调用,才能最终实现运行,所以将最外围的执行环境定义为全局执行环境,在宿主为web浏览器时,全局执行环境就为window对象。
每个函数都有自己的执行环境。当执行程序进入一个函数时,函数的环境就会被推入一个环境栈中。而在函数执行之后,栈将环境弹出,把控制权返回给之前的执行环境。之后,该环境因为执行完毕,随即被销毁。但有一个例外,全局环境将永远不会被销毁,直到程序被关闭,如关闭浏览器。
由上图我们清晰的看到JavaScript的两个阶段的执行流程。
2、作用域与作用域链
作用域链和作用域是一个包含关系。当代码在一个环境中执行时,会创建变量对象的一个作用域链。而作用域链中,包含的就是一个个有序排列的作用域。作用域链的作用,就是保证执行环境中的变量和函数的有序访问。
每次的变量或函数声明,都会形成一个标识符(即变量名或函数名)。 作用域链中的向上查找,实际上就是标识符的查找。找到匹配的标识符,就调用它的值。
作用域链中包含的每个作用域对象,其中都包含着它自身环境中可访问的变量或函数(script作用域中,为全部的变量和函数;函数作用域中,子函数调用父函数环境中的变量或函数会形成闭包,那么可访问变量就为闭包调用的变量)。换一种角度理解的话,这些环境中可访问的变量或函数就是标识符,是当前作用域中可通过作用域链向上查找的标识符。
一大段的文字不光读起来枯燥,理解起来也困难。所以,stop talking,show code。
以函数为例
function test() {let a = 1; //注释此行,保留其他a,c()打印2,并且作用域链失去闭包对象let b = 0;return () => { //形成闭包环境console.log(a);}}let a = 2; //注释此行及test中的a,c()打印3window.a = 3; //注释全部a,报错const c = test();c();console.dir(test);console.dir(c);
以上代码,通过3次注释以及chrome浏览器打印,可以清晰的看到作用域与作用域链的形成及作用域链按顺序查找的特性
1)首先是闭包调用——所有a都不注释
由上图可以看出,此时作用域链中存在3个作用域对象。 按索引顺序为0—Closure闭包环境、1—Script标签环境、2—Global全局环境;
索引顺序就是标识符的查找顺序,所以当执行函数c()时,先在Closure闭包环境中查找,然后是Script标签作用域,最后是Global全局作用域。因为形成了闭包,那么标识符的查找肯定能在闭包环境中找到对应结果,所以打印1;
值得注意的一点是,Closure与Script作用域对象中,存储的标识符的不同。closure只存储调用值a = 1,并没有存储b = 0。而Script中将环境中的所有标识符都存在了对象中;
2)然后是取消闭包调用,改为Script标签作用域查找——注释test中的a = 1
由上图可以看出,此时作用域链中的Closure闭包作用域消失,只剩下2个对象0—Script标签环境、2—Global全局环境;
那么同样按索引顺序查找,找到了Script标签环境中的a = 2,没有继续寻找Global全局环境中的window.a = 3,最终打印2;
3)最后是Global全局作用域查找——注释test中的a = 1及script中的a = 2
与2)中情况对比,作用域链中的对象没有改变。但是Script对象中的标识符,随着a = 2被注释而消失
按索引顺序查找,找到了Script标签环境中没有a,继续寻找Global全局环境,最终找到window.a = 3,打印3;
函数test的打印,从始至终都是Script标签作用域及Global全局作用域。理解了c函数的作用域链,自然就明白了函数test的,所以不再展开赘述。
如有错误或阐述不充分之处,欢迎指正~
转载于:https://www.cnblogs.com/keepStudying/p/9870409.html
javascript精雕细琢(三):作用域与作用域链相关推荐
- JavaScript 开发进阶:理解 JavaScript 作用域和作用域链(上)
作用域是JavaScript最重要的概念之一,想要学好JavaScript就需要理解JavaScript作用域和作用域链的工作原理.今天这篇文章对JavaScript作用域和作用域链作简单的介绍,希望 ...
- Javascript的作用域,作用域链,闭包
1,作用域和作用域链概念 作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期.在JavaScript中,变量的作用域有全局作用域和局部作用域两种. 1.1 全局作用域,在代码 ...
- JavaScript 中的闭包和作用域链(读书笔记)
要想理解闭包,应当先理解JavaScript的作用域和作用域链. JavaScript有一个特性被称之为"声明提前(hoisting)",即JavaScript函数里声明的所有变量 ...
- JavaScript(三)—— JavaScript 函数/JavaScript 作用域/JavaScript 预解析/JavaScript 对象
本篇为 JavaScript 系列笔记第三篇,将陆续更新 JavaScript(一)-- 初识JavaScript/注释/输入输出语句/变量/数据类型 JavaScript(二)-- JavaScri ...
- JavaScript 开发进阶:理解 JavaScript 作用域和作用域链
作用域是JavaScript最重要的概念之一,想要学好JavaScript就需要理解JavaScript作用域和作用域链的工作原理.今天这篇文章对JavaScript作用域和作用域链作简单的介绍,希望 ...
- 【07】JavaScript:05-作用域、变量的作用域、作用域链、预解析、对象
文章目录 JavaScript基础第05天笔记 1 - 作用域 1.1 作用域概述 1.2 全局作用域 1.3 局部作用域 1.4 JS没有块级作用域 2 - 变量的作用域 3 - 作用域链 4 - ...
- 图解 | JavaScript的作用域和作用域链
文 / 景朝霞 来源公号 / 朝霞的光影笔记 ID / zhaoxiajingjing 图 / 自己画 ❥❥❥❥点个赞,让我知道你来过~❥❥❥❥ 前情提要: 题目 | let和var的区别(一.二) ...
- js面试与笔试---理解 JavaScript 作用域和作用域链
任何程序设计语言都有作用域的概念,简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期.在JavaScript中,变量的作用域有全局作用域和局部作用域两种. 1. ...
- [未完整]JavaScript 开发进阶:理解 JavaScript 作用域和作用域链
转载:http://www.cnblogs.com/lhb25/archive/2011/09/06/javascript-scope-chain.html 作用域是JavaScript最重要的概念之 ...
最新文章
- 开源Android或将收费
- 一个自己写的PHP模板引擎
- wifi漫游测试过程
- IOS 粒子发射器,雪花落下、创建火焰、河流、蒸汽的动画效果源代码
- NLP领域近期有哪些值得读的开源论文?
- python分类预测降低准确率_python实现吴恩达机器学习练习3(多元分类器和神经网络)...
- FTP两种工作模式:主动模式(Active FTP)和被动模式(Passive FTP)
- java常用类总结_java——常用类的总结
- Matplotlib - 柱状图、直方图、条形图 bar() barh() 所有用法详解
- [JavaScript] 判断网页能不能被IFrame 嵌入
- 哈夫曼算法(最优二叉树)
- MapJoin的原理及案例
- apch连接mysql数据库连接_配置phpmyadmin连接远程 MySQL数据库
- 电子纸BUSY引脚不同状态下说明(大连佳显)
- 每日新闻:亚马逊加速推进自研芯片 英特尔领先地位岌岌可危;电信、移动、百度等76家企业被工信部纳入2018年“黑名单”...
- ArcGIS Runtime SDK for Android 读取tpk、vtpk
- 自然语言处理(NLP)概论
- 传奇服是怎样架设的,怎样搭建一个属于自己的游戏服 10分钟学会游戏架设 玩转云服务器搭建游戏
- socket编程——upd(数据报套接字)
- 浅谈C语言自定义类型枚举和联合体以及对结构体位段的补充
热门文章
- 如何为团队选择有用的增量进度衡量标准
- 谷歌推出 Kotlin 免费在线课程
- python引用模块的私有变量_python 使用不同方法导入模块,模块中私有变量的使用区别...
- 管理动物园动物c++_中国动物园行业供需预测及投资潜力分析
- linux下python脚本print中文显示不正确_pythoncgi脚本不会在linux上打印希伯来语
- 计算机网络系统是弱电工程,弱电工程包括哪些类型?常见的问题又有哪些?
- java 多线程操作map_Java 多线程中ConcurrentHashMap并发读写操作范例
- php数据库单循环显示,php利用while单循环实现100行10列表格输出且每行颜色不一样...
- mysql 处理文件函数_mysql数据处理与函数
- jira 查找issue_JIRA使用教程:高级搜索—字段参考4/4