JavaScript的作用域和闭包
首发于:https://mingjiezhang.github.io/
闭包和作用域有着千丝万缕的联系。
js的作用域
具体的作用域我就不展开叙述了。其中很重要的两点就是:js的作用域链机制和函数词法作用域在定义的时候就确定的。对于前者,js中每个函数都有自己的执行环境,执行流进入一个函数时,函数的环境就会被推入一个环境栈,函数执行完之后就把控制权归还,这也是垃圾回收机制的原理,当代码在一个环境中执行会创建变量对象一个作用域链,标识符解析是沿着作用域链一级一级搜索的。对于后者,有些人认为函数词法作用域是执行时确定的,但这是错误的,本身词法作用域的定义就于此违背,我们可以通过下面这个例子来证明。
function b(){
var x=3;
a();
}
function a(){
console.log(x);
}
b();//x is not defined.
如果函数作用域是执行时候确定的,那么按理结果应该是打印3。但是我们看到是x未定义,这完美地证明了a()的作用域链中是不存在b()的局部作用域。因此,我们可以确定函数词法作用域在定义的时候就确定的。
作个小总结:函数作用域是在函数定义的时候就确定了的,但是只有函数作用域需要通过执行函数来激活函数局部作用域,如果未执行函数或者函数执行完毕,该函数的变量对象的作用域都是不能被使用的或者被回收的,这点对于理解闭包十分重要。
初探闭包
闭包的定义有很多,在《You dont'konw JavaScript》中闭包的定义:当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行。
我们来解读下这句话,闭包怎么产生,就是一个内部函数可以记住它所在的作用域的时候,这个函数就是个闭包了,而且,这个函数在这个作用域外执行的时候,也是可以记住该作用域的。
我们先通过一个demo来解析这个定义。
function out(){
var a=1;
function in(){
console.log(a);
}
return in;
}//定义out函数
var temp=out();//将out函数执行返回的in函数引用赋值给temp变量
temp();//结果输出1
假如没有闭包:按照js的垃圾回收机制,在out()函数执行完毕的时候,out的内部作用域应该被销毁,也就是这时候变量a本应该销毁,这时候函数temp()中无法获得a声明所在的作用域。
不过闭包却可以改变这一切,out函数在执行完毕后,out内部作用域仍然存在。这时候,temp()函数执行的时候,可以记住并访问out()内部的作用域,这时候temp()函数可以访问a。
这就是闭包的神奇之处,虽然外部函数执行完毕,但是内部函数如果有变量引用外部函数作用域中的变量,那么该外部函数的变量对象就不会被回收,可以继续被使用。
闭包的意义和危险
闭包的意义就是可以让一个外部函数中的内部函数在非当前作用域中被使用,同时这个内部函数可以操作外部函数的作用域中的变量。模块的实现与闭包有很联系。具体的例子这边不展开叙述。
当然闭包也很危险,因为外部函数执行完毕后,外部函数的作用域的变量对象一直被引用,长期未被回收会造成内存泄漏,因此我们需要手动去销毁这些被引用的变量。
欢迎指正交流。未经允许,请勿转载。
JavaScript的作用域和闭包的更多相关文章
- 我认知的javascript之作用域和闭包
说到javascript,就不得不说javascript的作用域和闭包:当然,还是那句老话,javascript在网上都说得很透彻了,我也就不过多的强调了: 作用域:javascript并没有像其他的 ...
- 剖析JavaScript函数作用域与闭包
在我们写代码写到一定阶段的时候,就会想深究一下js,javascript是一种弱类型的编程语言,而js中一个最为重要的概念就是执行环境,或者说作用域.作用域重要性体现在哪呢?首先,函数在执行时会创建作 ...
- 你不知道的JavaScript(作用域和闭包)
作用域和闭包 ・作用域 引擎:从头到尾负责整个JavaScript的编译及执行过程. 编译器:负责语法分析及代码生成等. 作用域:负责收集并维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非 ...
- JavaScript 函数作用域和闭包
函数作用域和闭包 词法作用域 它们在定义它们的作用域里运行,而不是在执行的作用域运行,但是只有在运行时,作用域链中的属性才被 定义(调用对象),此时,可访问任何当前的绑定. 调用对象 ...
- JavaScript从作用域到闭包
目录 作用域 全局作用域和局部作用域 块作用域与函数作用域 作用域中的声明提前 作用域链 函数声明与赋值 声明式函数.赋值式函数与匿名函数 代码块 自执行函数 闭包 作用域(scope) 全局作用域 ...
- javascript的作用域和闭包(三)闭包与模块
一些很重要的说明:前面三篇博客详细的介绍了,引擎与编译器和作用域的关系,重点需要理解的是编译器中的分词与词法分析,JavaScript的特有的“赋值操作的左右侧”引用操作:编译阶段的词法作用域的工作原 ...
- JavaScript的作用域与闭包
JavaScript的作用域以函数为界,不同的函数拥有相对独立的作用域.函数内部可以声明和访问全局变量,也可以声明局部变量(使用var关键字,函数的参数也是局部变量),但函数外部无法访问内部的局部变量 ...
- JavaScript之作用域和闭包
一.作用域 作用域共有两种主要的工作模型:第一种是最为普遍的,被大多数编程语言所采用的词法作用域,另外一种叫作动态作用域: JavaScript所采用的作用域模式是词法作用域. 1.词法作用域 词法作 ...
- 前端知识体系:JavaScript基础-作用域和闭包-JavaScript的作用域和作用域链
JavaScript的作用域和作用域链 作用域: 变量的作用域无非两种:全局作用域和局部作用域 全局作用域: 最外层函数定义的变量拥有全局作用域.即对任何内部函数来说都是可以访问的. <scri ...
- Javascript的作用域和闭包(一)
一.作用域是什么? 几乎所有的编程语言最基本的功能之一,就是能够存储变量的值,并且能访问和修改这些值. 修改变量值的过程我们通常在程序执行时,称为改变一个对象的状态.有了状态,让程序变得有非常有趣. ...
随机推荐
- POJ 2082 Terrible Sets
Terrible Sets Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 2747 Accepted: 1389 Des ...
- oracle数据库的字符集更改
A.oracle server 端 字符集查询 select userenv('language') from dual 其中NLS_CHARACTERSET 为server端字符集 NLS_LAN ...
- Form personization(Form 个性化)报无权限
总部的同事利用form personization对工单的一些Form做了个性化,发现可能设的有问题,造成用户无法关工单.想要看一下她是怎么设的,可报没权限.经过研究发现,把个人Profile 的 U ...
- PowerShell 启动应用程序【转】
当你在PowerShell中,启动带参数启动可执行应用程序时,可能会碰到参数解析的错误.最好的方式是使用命令 Start-Process,该命令有两个优点: 程序的路径和程序参数分开,可以使用-Fil ...
- 【转】Linux下svn常用指令
转自: http://blog.csdn.net/myarrow/article/details/8110858 1.将文件checkout到本地目录svn checkout path(path是服务 ...
- IMongoQuery的内部实现Query的用法
Query.All("name", "a", "b");//通过多个元素来匹配数组 Query.And(Query.EQ("nam ...
- Tips10:你可以像写文档一样自由的复制粘贴游戏组件(Game Object Component)
相对于添加组件后再进行调整和赋值,通过复制和粘贴已有游戏组件能够带来更高的效率.
- 【转载】Debian/Ubuntu常见安装软件错误解决方案
转载自:http://blog.csdn.net/eqera/article/details/6375293 1.错误: Can't find X includes. Please check you ...
- Android 学习笔记之Volley开源框架解析(四)
学习内容: 1.NetWorkDispatcher网络请求线程调度... 2.NetWork网络请求抽象类... 3.BasicNetWork网络请求抽象类的具体实现... 4.NetWorkResp ...
- The Linux Process Principle,NameSpace, PID、TID、PGID、PPID、SID、TID、TTY
目录 . 引言 . Linux进程 . Linux命名空间 . Linux进程的相关标识 . 进程标识编程示例 . 进程标志在Linux内核中的存储和表现形式 . 后记 0. 引言 在进行Linux主 ...