Ref: 为什么要用闭包?

背景

闭包是自带运行环境的函数

发哥是自带背景音乐的男人~

就是有权访问另一个函数作用域的变量的函数。

函数式编程的闭包,就是函数的调味包。
方便用户调用函数。不必为了维护繁杂的外部状态而烦恼。

我们常见的闭包形式就是:【基于静态作用域的一个编程技巧】

(1) a 函数套 b 函数,

(2) 然后 a 函数返回 b 函数,

这样 b 函数在 a 函数以外的地方执行时,依然能访问 a 函数的作用域。

其中 “b 函数在 a 函数以外的地方执行时” 这一点,才体现了闭包的真正的强大之处。

静态作用域

Ref: 浅谈静态作用域和动态作用域

Ref: JavaScript 词法、静态、动态作用域初级理解

若干需要关注点(概念)

  1)执行环境(作用域)函数执行环境 变量作用域

  2)函数作用域和声明提前

  3)自由变量

  4)词法作用域和静态作用域

  5)动态作用域

1)执行环境(作用域)函数执行环境 变量作用域

每个执行环境都有一个与之关联的“变量对象(variable object)”,环境中定义的所有变量和函数都保存在这个对象中。我们编写的代码是无法访问这个对象的,但解析器在处理数据时会在后台使用它。

全局执行环境是最外围的一个执行环境,在Web浏览器中,全局执行环境被认为是window对象,因此所有全局变量和函数都是作为window对象的属性和方法来创建的。某个执行环境中的所有代码执行完毕后,该环境就会被销毁,保存在其中的所有变量和函数定义也随之销毁。

函数执行环境:每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。 

作用域链:它的用途是保证对执行环境有权访问的所有变量和函数的有序访问,作用域链的前端,始终都是当前执行的代码所在的环境的变量对象。当代码在一个执行环境中执行时,会创建变量对象的一个作用域链(scope chain)。

2)声明提前

【不怎么理解原例子】

3)自由变量:在A作用域中使用的变量x,却没有在A作用域中声明(即在其他作用域中声明的),对于A作用域来说,x就是一个自由变量。

var x = 10;
function fn(){
var b = 20;
console.log(x + b); // <---- x 就是一个自由变量。
}

4)词法作用域和静态作用域:词法作用域等同于静态作用域,静态作用域规则查找一个变量声明时依赖的是源程序中块之间的静态关系;【JavaScript 是使用词法作用域】

5)动态作用域规则依赖的是程序执行时的函数调用顺序。

静态作用域和动态作用域的一个重要区别在于:
  * 静态作用域规则查找一个变量声明时依赖的是源程序中块之间的静态关系;
  * 而动态作用域规则依赖的是程序执行时的函数调用顺序。
说的具体点,就是静态作用域查找的是距离当前作用域最近的外层作用域中同名标识符的声明,
而动态作用域则是查找最近的活动记录。

大多数现在程序设计语言都是采用静态作用域规则,

而只有为数不多的几种语言采用动态作用域规则,包括APL、Snobol和Lisp的早期方言。

而采用静态作用域的语言中,基本都是最内嵌套作用域规则:由一个声明引进的标识符在这个声明所在的作用域里可见,而且在其内部嵌套的每个作用域里也可见,除非它被嵌套于内部的对同名标识符的另一个声明所掩盖。为了找到某个给定的标识符所引用的对象,应该在当前最内层作用域里查找。如果找到了一个声明,也就可以找到该标识符所引用的对象。否则我们就到直接的外层作用域里去查找,并继续向外顺序地检查外层作用域,直到到达程序的最外嵌套层次,也就是全局对象声明所在的作用域。如果在所有层次上都没有找到有关声明,那么这个程序就有错误。

Ref: Javascript之旅——第十站:为什么都说闭包难理解呢?

例子一:

闭包变量:name

<script type="text/javascript">

        //比较函数
function createComparison(propertyName) { return function ( obj1, obj2 ) {

var item1 = obj1[propertyName];
var item2 = obj2[propertyName]; if (item1 < item2)
return -1; if (item1 > item2)
return 1; if (item1 == item2)
return 0;
}
} //比较name
var compare = createComparison("name"); var result = compare( { name: "d", age: 20 }, { name: "c", age: 27 } );
</script>

注意对下面这个列表所表示的scope的检索范围优先级的理解。

例子二:

<script type="text/javascript">

        var arr = new Array();

        function Person() {
for (var i = 0; i < 10; i++) { //要记住,这个属性函数申明,只有立即执行才会取scope属性,但这里不会立即执行,哈哈
var item = function () {
return i;
}; arr.push(item);
}
} Person(); for (var i = 0; i < arr.length; i++) {
console.log(arr[i]());
}
</script>

给匿名函数再增加一个副本。

<script type="text/javascript">

        var arr = new Array();

        function Person() {
for (var i = 0; i < 10; i++) { var item = function (num) {
return function () {    // 给每个匿名function一个副本就好了
return num;
}
} (i); arr.push(item);
}
} Person(); for (var i = 0; i < arr.length; i++) {
console.log(arr[i]());
}
</script>
延长作用域链:
无论函数在哪里被调用或者如何被调用,它的词法作用域都只由函数被声明时所处的位置决定,
所以,函数所能访问变量的"权限"只由声明位置决定,利用这个特性就可以利用闭包(将这个函数return出去,该函数声明位置不变,
所以可访问变量的"权限"依然不变)使函数外部可以访问函数内部的变量。
 

[JS] Topic - this is ”closure“的更多相关文章

  1. [JS] Topic - why "strict mode" here

    Ref: Javascript 严格模式详解 使得Javascript在更严格的条件下运行: - 消除Javascript语法的一些不合理.不严谨之处,减少一些怪异行为; - 消除代码运行的一些不安全 ...

  2. 三个JS函数闭包(closure)例子

    闭包是JS较难分辨的一个概念,我只是按自己的理解写下来,如有不对还请指出. 函数闭包是指当一个函数被定义在另一个函数内部时,这个内部函数使用到的变量会被封闭起来形成一个闭包,这些变量会保持形成闭包时设 ...

  3. [JS] Topic - variable and function hoisting

    Ref: 深入理解js的变量提升和函数提升 一.变量提升 简直就是es5的遗毒! console.log(global); // undefined 竟然能打印?因为变量提升,下一行就有定义 var ...

  4. [JS] Topic - Object.create vs new

    故事背景 Ref: 你不知道的javascript之Object.create 和new区别 var Base = function () {} (1) var o1 = new Base(); (2 ...

  5. [JS] Topic - hijack this by "apply" and "call"

    Ref: 详解js中的apply与call的用法 call 和 apply二者的作用完全一样,只是接受参数的方式不太一样. 参数形式: Function.apply(obj,args) call方法与 ...

  6. [JS] Topic - define "class" by tricky methods

    Ref:Javascript定义类(class)的三种方法 Javascript是一种基于对象(object-based)的语言,你遇到的所有东西几乎都是对象.但是,它又不是一种真正的面向对象编程(O ...

  7. [Code::Blocks] Install wxWidgets & openCV

    The open source, cross platform, free C++ IDE. Code::Blocks is a free C++ IDE built to meet the most ...

  8. 本人SW知识体系导航 - Programming menu

    将感悟心得记于此,重启程序员模式. js, py, c++, java, php 融汇之全栈系列 [Full-stack] 快速上手开发 - React [Full-stack] 状态管理技巧 - R ...

  9. JS,html压缩及混淆工具

    现在已经出现了不少有自己特色的: JSMin Javascript compressor Packer Closure Compiler YUI Compressor Pretty Diff Java ...

随机推荐

  1. 关于ADO.Net SqlConnection的性能优化

    Connections Database connections are an expensive and limited resource. Your approach to connection ...

  2. Android:使用shape制作素材

    最近看到朋友制作的Android APP使用了极少的图片,但是图形却极其丰富,问了之后得知是使用shape绘制的,有很多优点. 下面是我整理的一些素材: 预览 下面是图片预览: 代码 布局文件 < ...

  3. IEEE 754二进制浮点数算术标准

    可能很多人都遇到过浮点数精度丢失的问题,下面以JavaScript为例. 1 - 0.9 = 0.09999999999999998 纳尼,不应该是0.1么,怎么变成0.099999999999999 ...

  4. Fragment的可见再载入的方法(真正的Fragment的OnResume和OnPause)

    一 起因 我们在做应用的过程中,一个应用的界面可能是多个Fragment切换而成的.可是如果在每次应用启动的时候就去载入大量的网络数据(如果你的每一个Fragment都须要载入网络数据.你也能够理解为 ...

  5. linux修改目录为可读写

    发布到linux上遇到的问题, 上传目录没有写入权限 新建目录 mkdir /guangkuo/html/portal/images/upload 改为可读写 chmod -R a+w /guangk ...

  6. OpenCV学习代码记录——人脸检测

    很久之前学习过一段时间的OpenCV,当时没有做什么笔记,但是代码都还在,这里把它贴出来做个记录. 代码放在码云上,地址在这里https://gitee.com/solym/OpenCVTest/tr ...

  7. 你可能不知道的51个Linux经典命令

    1.删除0字节文件 代码如下: find -type f -size 0 -exec rm -rf {} \; 2.查看进程按内存从大到小排列 代码如下: ps -e -o "%C : %p ...

  8. maven本地库与私服比对,查找缺失jar包

    项目中遇到的一个问题,因为要切换开发环境(新环境不能联网,且私服上的jar包信息不全),需要将本地仓库(项目使用本地仓库能够正常编译)中有而私服上没有的jar包整理出来(名称.版本号等),提供给第三方 ...

  9. 2017 33 款iOS开源库

    IGListKit https://github.com/Instagram/IGListKit 由 Instagram 开发人员制作,IGListKit 是用于构建快速灵活列表的数据驱动型的 UIC ...

  10. Java中apache下面FtpClient主动模式和被动模式

    最近在做ftp文件上传的时候,开发测试环境上传都没有问题,但是在开发环境缺无法上传,但是也没有报错,纠结了老久.最后看到网上有说FtpClient有主动模式和被动模式之分,然后就解决了. FTPCli ...