js 作用域,作用域链,闭包
什么是作用域?
作用域是一种规则,在代码编译阶段就确定了,规定了变量与函数的可被访问的范围。全局变量拥有全局作用域,局部变量则拥有局部作用域。 js是一种没有块级作用域的语言(包括if、for等语句的花括号代码块或者单独的花括号代码块都不能形成一个局部作用域),所以js的局部作用域的形成有且只有函数的花括号内定义的代码块形成的,既函数作用域。
什么是作用域链?
作用域链是作用域规则的实现,通过作用域链的实现,变量在它的作用域内可被访问,函数在它的作用域内可被调用。
作用域链是一个只能单向访问的链表,这个链表上的每个节点就是执行上下文的变量对象(代码执行时就是活动对象),单向链表的头部(可被第一个访问的节点)始终都是当前正在被调用执行的函数的变量对象(活动对象),尾部始终是全局活动对象。
作用域链的形成?
我们从一段代码的执行来看作用域链的形成过程。
function fun01 () {
console.log('i am fun01...');
fun02();
}
function fun02 () {
console.log('i am fun02...');
}
fun01();

数据访问流程
如上图,当程序访问一个变量时,按照作用域链的单向访问特性,首先在头节点的AO中查找,没有则到下一节点的AO查找,最多查找到尾节点(global AO)。在这个过程中找到了就找到了,没找到就报错undefined。
关于闭包
1.什么是闭包?
函数对象可以通过作用域链相互关联起来,函数体内的数据(变量和函数声明)都可以保存在函数作用域内,这种特性在计算机科学文献中被称为“闭包”。既函数体内的数据被隐藏于作用于链内,看起来像是函数将数据“包裹”了起来。从技术角度来说,js的函数都是闭包:函数都是对象,都关联到作用域链,函数内数据都被保存在函数作用域内。
//闭包实例
function outerFun () {
var outerV1 = 10
function outerF1 () {
console.log('I am outerF1...')
} function innerFun () {
var innerV1 = outerV1
outerF1()
}
return innerFun //return回innerFun()内部函数
}
var fn = outerFun() //接到return回的innerFun()函数
fn() //执行接到的内部函数innerFun()
此时它的作用域链是这样的:

3.闭包的好处及使用场景
js的垃圾回收机制可以粗略的概括为:如果当前执行上下文执行完毕,且上下文内的数据没有其他引用,则执行上下文pop出call stack,其内数据等待被垃圾回收。而当我们在其他执行上下文通过闭包对执行完的上下文内数据仍然进行引用时,那么被引用的数据则不会被垃圾回收。就像上面代码中的outerV1,放我们在全局上下文通过调用innerFun()仍然访问引用outerV1时,那么outerFun执行完毕后,outerV1也不会被垃圾回收,而是保存在内存中。另外,outerV1看起来像不像一个outerFun的私有内部变量呢?除了innerFun()外,我们无法随意访问outerV1。所以,综上所述,这样闭包的使用情景可以总结为:
(1)进行变量持久化。
(2)使函数对象内有更好的封装性,内部数据私有化。
function countFun () {
var count = 0
return function(){
return count++
}
}
var a = countFun()
a()//0
a()//1,变量count没有被回收
4.闭包的注意事项
由于闭包中的变量不会像其他正常变量那种被垃圾回收,而是一直存在内存中,所以大量使用闭包可能会造成性能问题。
参考:http://www.cnblogs.com/ivehd/p/scopechain.html
js 作用域,作用域链,闭包的更多相关文章
- JS 之作用域链和闭包
1.JS无块级作用域 <script> function Main(){ if (1==1){ var name = "alex"; } console.log(nam ...
- 作用域 作用域链 闭包 思想 JS/C++比较
首先,我说的比较是指JS中这种思想/实现方式与C++编译原理中思想/实现方式的比较 参考链接:(比较易懂的介绍,我主要写个人理解) 作用域链: http://www.cnblogs.com/dolph ...
- js原型链闭包作用域链-Tom
1.原型相当于Java.C++里面的父类,由封装公有属性及方法而产生,子类可以继承. 原型继承实现(函数的原型属性指向原型函数一个实例对象,函数的原型的构造函数指向函数本身) 1)eg:原型链 fun ...
- js 函数 作用域 全局作用域 局部作用域 闭包
一个变量没有声明但调用 直接报错,声明没有赋值会显示未定义. 作用域 作用域(scope):一条数据可以在哪个范围中使用. 通常来说,一段程序代码中所用到的数据并不总是有效/可用的,而限定这个数据的可 ...
- js中作用域和闭包
作用域链实例 (1) function example() { var age = 23; alert(age) } var age = 25; example(); alert(age); // ...
- JS之作用域与闭包
JS之作用域与闭包 作用域在JS中同样也是一个重要的概念.它不复杂,因为ES5中只有全局作用域和函数作用域,我们都知道他没有块级作用域.但在ES6中多了一个let,他可以保证外层块不受内层块的影响 ...
- js中作用域链的问题
为什么没有var声明的变量是全局的? 是因为,在js中,如果某个变量没有var声明,会自动到上一层作用域中去找这个变量的声明语句,如果找到,就使用,如果没有找到,继续向上查找,一直查找到全局作用域为止 ...
- 聊一下JS中的作用域scope和闭包closure
聊一下JS中的作用域scope和闭包closure scope和closure是javascript中两个非常关键的概念,前者JS用多了还比较好理解,closure就不一样了.我就被这个概念困扰了很久 ...
- 你不知道的JS之作用域和闭包(五)作用域闭包
原文:你不知道的js系列 一个简单粗暴的定义 闭包就是即使一个函数在它所在的词法作用域外部被执行,这个函数依然可以访问这个作用域. 比如: function foo() { var a = 2; fu ...
- JS的作用域链与原型链
来一波,好记性不如烂笔头. 这两条链子可是很重要的. 作用域链 当执行一段JS代码(全局代码或函数)时,JS引擎会创建为其创建一个作用域又称为执行上下文(Execution Context),在页面加 ...
随机推荐
- 【Revit API】梁构件支座检查算法
一.前言 应该是第二次写关于Revit API的博文了.虽然在BIM企业中工作,从事桌面BIM软件开发,但是我是不怎么喜欢写Revit API相关的代码.平时更多的是在写界面展示,架构 ...
- Twitter的分布式系统中ID生成方法——Snowflake
Twitter-Snowflake算法产生的背景相当简单,为了满足Twitter每秒上万条消息的请求,每条消息都必须分配一条唯一的id,这些id还需要一些大致的顺序(方便客户端排序),并且在分布式系统 ...
- PHP浮点型(float)转换为整形(int)/round()保留小数点后几位
round(x,y); x:需要转换的变量 y:保留几位小数 <?php echo round(3.112312321) //输出3 echo round(3.112312321,3) //输出 ...
- 创建文件DSN
记录:为了将access中表格直接上传到SQL中,不用在SQL中进行再创建. 优点:不用经过系统来生成,直接手动产生.(主要是搜索到的资料不足以一下搞出来,抱着试试的心态,最后成功了!) 操作步骤: ...
- Windows下memcached的安装配置
下载windows 32位或64位 memcached 下载 memcached_dll 1.将第一个包解压放某个盘下面,比如在c:\memcached.2.在终端(也即cmd命令界面)下输入 'c: ...
- ASP.NET Core 2.0 支付宝当面付之扫码支付
前言 自从微软更换了CEO以后,微软的战略方向有了相当大的变化,不再是那么封闭,开源了许多东西,拥抱开源社区,.NET实现跨平台,收购xamarin并免费提供给开发者等等.我本人是很喜欢.net的,并 ...
- binary
模块说明 函数经过优化,比等价Erlang实现(比如位语法)更快,更节省内存 大部分可用位语法等价实现 模块的实现根据EEP(Erlang Enhancement Proposal)31 模块只处理面 ...
- 让asp.net网站支持多语言,使用资源文件
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="test.aspx.cs&quo ...
- 使用C#系统服务定时执行操作
1.新建项目 --> Windows 服务 2.Service1.cs代码 using System; using System.Collections.Generic; using Syste ...
- SQL查找 删除重复数据只保留一条
--用SQL语句,删除掉重复项只保留一条 --在几千条记录里,存在着些相同的记录,如何能用SQL语句,删除掉重复的呢 --1.查找表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断 ...