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的作用域和闭包(一)
一.作用域是什么? 几乎所有的编程语言最基本的功能之一,就是能够存储变量的值,并且能访问和修改这些值. 修改变量值的过程我们通常在程序执行时,称为改变一个对象的状态.有了状态,让程序变得有非常有趣. ...
随机推荐
- Word2010撤销按钮失效,Ctrl+Z失效解决办法
1.打开注册表编辑器.按Win+R,在运行框中键入regedit,然后单击“确定”. 2.在注册表编辑器中,展开到下列注册表子项: HKEY_CURRENT_USER\Software\Microso ...
- iOS 7新功能例子
参考https://github.com/shu223/iOS7-Sampler Code examples for the new functions of iOS 7. Contents Dyna ...
- Android中使用自身携带的Junit新建一个测试工程
1.新建立一个Android工程 package com.shellway.junit; public class Service { public int divide(int a,int b){ ...
- 【转载】solr初体验
[1]http://cxshun.iteye.com/blog/1039445 由于工作原因,这段时间接触到solr,一个基于lucene的企业级搜索引擎.不怎么了解它的童鞋可以去GOOGLE一下. ...
- LED子系统剖析
写之前,先看一张图: 上次说了LED驱动程序,Linux自身也携带了LED驱动,且是脱离平台的,即LED子系统.操作起来十分简单.但是它的实质却不是那么容易,研究了一个晚上,终于明白了其中一个文件的功 ...
- smartjs 0.3 DataManager 发布&介绍
在0.3版加入了DataManager,基于策略的数据管理模块:是SmartJS中比较重要的一个系列.整个个DataManager模块包括有:dataManager,dataPolicyManager ...
- MyBatis知多少(5)业务对象模型
几乎所有结构良好的软件都使用了分层设计.分层设计将一个应用程序根据技术职能分为几 个内聚的部分,从而将某种特定技术或接口的实现细节与其他部分分离开来.分层设计可以用任 何一种强壮的编程语言来实现.图1 ...
- The connection to adb is down, and a severe error has occured.(DDMS中没有真机)
最近老是出现真机用着用着就掉线了,在DDMS中看不到,运行项目出现选择运行机器中也没有,360助手连接电脑OK,任务管理器中没有adb.exe,重启eclipse不行,只能每次重启电脑.按照http: ...
- 欲善其事必先利其器---Xcode插件
Xcode所有的插件都安装在目录~/Library/Application Support/Developer/Shared/Xcode/Plug-ins/ Alcatraz (用于管理xcode插件 ...
- android resources使用总结
http://developer.android.com/guide/topics/resources/more-resources.html http://developer.android.com ...