04:JavaScript 的闭包

一、定义:

常规定义:

闭包的定义: 有权利访问外部函数作用域的函数。

通俗定义:

1、函数内部包含了函数。然后内部函数可以访问外部函数的作用域。
2、内部函数可以访问 父级函数的作用域。
...等等等
二、思考:
1、我们在日常的开发过程中会应用到 闭包么?
2、如果有遇到的话,会是在什么情况下遇到的?
3、举一些 具体的例子。

1、我们在日常的开发过程中会应用到 闭包么?

以之前的知识对于 闭包的理解来讲是这样的

(function(){
for(var i=0; i<10; i++) {
console.log(i)
}
})()
或者说是这样的

var fnX = function() {
var x = 123
function y() {
alert(x)
}
y()
} fnX() // 123

总结下之前的理解就是: 内部函数能访问外部函数作用域,能够保存变量不被销毁而一直存在。

三、作用:

在JavaScript中有作用域和执行环境的问题,在函数内部的变量在函数外部是无法访问的,在函数内部却可以得到全局变量。由于种种原因,我们有时候需要得到函数内部的变量,可是用常规方法是得不到的,这时我们就可以创建一个闭包,用来在外部访问这个变量。

通过将一个方法或者属性声明为私用的,可以让对象的实现细节对其他对象保密以降低对象之间的耦合程度,可以保持数据的完整性并对其修改方式加以约束,这样可以是代码更可靠,更易于调试。封装是面向对象的设计的基石。

3.1 什么是作用域
3.1.1 ES5的作用域问题
在 ES5 中 我们常常会说的一个概念是 局部变量 和 全局变量

那么 局部变量 和 全局变量 所这个 局部 和 全局则为 作用域。

这个概念其实介绍起来还是比较多虚无。 但是我记得有一本书 叫 《你不知道的JS》

在这本书的 上册 作者详细的介绍了 作用域 这个概念。

作用域是什么

  1.现代JavaScript已经不再是解释执行的,而是编译执行的。但是与传统的编译语言不同,它不是提前编译,编译结果不能进行移植。编译过程中,同样会经过分词/词法分析,解析/语法分析,代码生成三个阶段。

  2.以var a = 2;语句为例,对这一程序语句对处理,需要经过引擎,编译器,作用域三者的配合。其中,引擎从头到尾负责整个javascript程序的编译和执行过程;编译器负责语法分析和代码生成;作用域负责收集并维护由所有声明的标识符组成的系列查询,并实施一套规则,确定当前执行的代码对这些标识符的访问权限。

  3.对于var a = 2;编译器首先查找作用域中是否已经有该名称的变量,然后引擎中执行编译器生成的代码时,会首先查找作用域。如果找到就执行赋值操作,否则就抛出异常

  4.引擎对变量的查找有两种:LHS查询和RHS查询。当变量出现中赋值操作左侧时是LHS查询,出现中右侧是RHS查询

词法作用域

1.词法作用域就是定义在词法阶段的作用域。词法作用域是由你在写代码时将变量和块作用域写在哪里决定的,词法处理器分析代码时会保持作用域不变

2.作用域查找会在找到第一个匹配的标识符时停止

3.eval和with可以欺骗词法作用域,不推荐使用

函数作用域和块作用域

1.JavaScript具有基于函数的作用域,属于这个函数的变量都可以在整个函数的范围内使用及复用
2.(function fun(){})() 函数表达式和函数声明的区别是看function关键字出现在声明中的位置。如果function是声明中的第一个词,那么就是一个函数声明,否则就是一个函数表达式 3.with,try/catch具有块作用域,方便好用的实现块级作用域的是es6带来的let关键字

提升

	1. 变量的提升
2. 函数提升 (这里就不过多的赘述了)

动态作用域

  1.词法作用域是一套引擎如何寻找变量以及会在何处找到变量的规则。词法作用域最重要的特征是它的定义过程发生中代码的书写阶段

  2.动态作用域让作用域作为一个在运行时就被动态确定的形式,而不是在写代码时进行静态确定的形式。eg:
function foo(){
console.log(a); // 2
}
function bar(){
var a = 3;
foo();
}
var a = 2;
bar();
词法作用域让foo()中的a通过RHS引用到了全局作用域中的a,所以输出2;动态作用域不关心函数和作用域如何声明以及在何处声明,只关心从何处调用。换言之,作用域链是基于调用栈的,而不是代码中的作用域嵌套。如果以动态作用域来看,上面代码中执行时会输出3

  3.JavaScript不具备动态作用域,但是this机制中某种程度上很像动态作用域,this关注函数如何调用。
3.1.2 ES6的作用域问题
在 ES6 中 出现了块级作用域的概念

let const 在() 内则 ()内的作用域 为 块级作用域。
3.2 什么是执行环境
执行环境 即为 当前作用域内的环境。
3.3 什么是作用域链
这个概念其实 也是比较虚的概念,不太好理解。但是一旦理解就不会忘记了。

所谓 链 其实就是链条, 将需要链接在一起的东西链接在一起(感觉说了一句废话)

作用域链的通俗理解:

在函数内部作用域 通过 作用域链 可以访问 函数外部作用域 的属性或者方法。

一层层的 作用域链 往外走  到最后 则为 window 对象的全局作用域。

然后这一条条的 作用域链 就形成了一整条关联的链条。
四、具体案例的分析:

这里 我们举了一个栗子

《前端之路》之四 JavaScript 的闭包、作用域、作用域链的更多相关文章

  1. Javascript中闭包的作用域链

    作用域定义了在当前上下文中能够被访问到的成员,在Javascript中分为全局作用域和函数作用域,通过函数嵌套可以实现嵌套作用域. 闭包一般发生在嵌套作用域中.闭包是JavaScript最强大的特性之 ...

  2. javascript中闭包与作用域的理解

    很多js的框架与插件编写都用到了闭包,所以,阅读和掌握闭包很有必要.最近学习vue框架时,经常会猜想很多功能的native js实现,很多都应用到了闭包,闭包除了目前已知的一些特性,如:可以保持局部变 ...

  3. javascript关于闭包变量作用域

    在项目中不时会遇到的一些小的问题以及解决办法: 1子函数调用父函数中的变量: 加return: var a=1; function num(){ var b=2; return b; } num()+ ...

  4. 前端知识体系:JavaScript基础-原型和原型链-理解 es6 中class构造以及继承的底层实现原理

    理解 es6 中class构造以及继承的底层实现原理 原文链接:https://blog.csdn.net/qq_34149805/article/details/86105123 1.ES6 cla ...

  5. 前端知识体系:JavaScript基础-原型和原型链-理解JavaScript的执行上下文栈,可以应用堆栈信息快速定位问题

    理解JavaScript的执行上下文栈,可以应用堆栈信息快速定位问题(原文文档) 1.什么是执行上下文: 简而言之,执行上下文就是当前JavaScript代码被解析和执行时所在环境的抽象概念,Java ...

  6. 前端知识体系:JavaScript基础-原型和原型链-理解原型设计模式以及 JavaScript中的原型规则

    理解原型设计模式以及 JavaScript中的原型规则(原文地址) 1.原型对象:我们创建的每一个函数(JavaScript中函数也是一个对象)都有一个原型属性 prototype,原型属性实质上是一 ...

  7. 前端知识体系:JavaScript基础-原型和原型链-new一个对象的详细过程,手动实现一个 new操作符

    可以描述 new一个对象的详细过程,手动实现一个 new操作符 1. new 一个对象的详细过程:(原文地址) 首先我们看下new Person输出什么? var Person = function( ...

  8. 前端知识体系:JavaScript基础-原型和原型链-实现继承的几种方式以及他们的优缺点

    实现继承的几种方式以及他们的优缺点(参考文档1.参考文档2.参考文档3) 要搞懂JS继承,我们首先要理解原型链:每一个实例对象都有一个__proto__属性(隐式原型),在js内部用来查找原型链:每一 ...

  9. 前端知识体系:JavaScript基础-原型和原型链-instanceof的底层实现原理

    instanceof的底层实现原理(参考文档) instanceof的实现实际上是调用JS的内部函数 [[HasInstance]] 来实现的,其实现原理是:只要右边变量的prototype在左边变量 ...

随机推荐

  1. 转载:selenium webdriver定位不到元素的五种原因及解决办法

    1.动态id定位不到元素for example:        //WebElement xiexin_element = driver.findElement(By.id("_mail_c ...

  2. 转[@SuppressWarnings详解]

    背景知识:       从JDK5开始提供名为Annotation(注释)的功能,它被定义为JSR-175规范.注释是以“@注释名”在代码中存在的,还可以添加一些参数 值,例如:@SuppressWa ...

  3. config.go

    package blog4go import ( "encoding/xml" "errors" "io/ioutil" "os& ...

  4. 【bzoj1758】[Wc2010]重建计划

    Description Input 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案, ...

  5. 【卡特兰数】BZOJ1485: [HNOI2009]有趣的数列

    Description 我们称一个长度为2n的数列是有趣的,当且仅当该数列满足以下三个条件: (1)它是从1到2n共2n个整数的一个排列{ai}: (2)所有的奇数项满足a1<a3<…&l ...

  6. POJ_3304_Segments_线段判断是否相交

    POJ_3304_Segments_线段判断是否相交 Description Given n segments in the two dimensional space, write a progra ...

  7. Form表单 JSON Content-type解析

    Form表单 JSON Content-type解析 1 表单Form概述 在Form表单中,参数一般有: action 表单提交的url method 提交方式:post get name 表单的属 ...

  8. AMBA总线协议AHB、APB

    一.什么是AMBA总线 AMBA总线规范是ARM公司提出的总线规范,被大多数SoC设计采用,它规定了AHB (Advanced High-performance Bus).ASB (Advanced ...

  9. 循环table 示例

    1.循环table里的某一列 //当前第三列 //注:索引从1开始 $("#tabcardno tr td:nth-child(3)").each(function () { va ...

  10. Python爬虫入门教程 64-100 反爬教科书级别的网站-汽车之家,字体反爬之二

    说说这个网站 汽车之家,反爬神一般的存在,字体反爬的鼻祖网站,这个网站的开发团队,一定擅长前端吧,2019年4月19日开始写这篇博客,不保证这个代码可以存活到月底,希望后来爬虫coder,继续和汽车之 ...