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. 机器学习笔记(6):多类逻辑回归-使用gluon

    上一篇演示了纯手动添加隐藏层,这次使用gluon让代码更精减,代码来自:https://zh.gluon.ai/chapter_supervised-learning/mlp-gluon.html f ...

  2. Tracking Boost Regulator TYPICAL 5V REGULATION WITH BOOST CONVERTER AND LDO

    Cs5171: Tracking Boost Regulator Adding a current mirror circuit to a typical boost circuit allows t ...

  3. Next Permutation leetcode java

    题目: Implement next permutation, which rearranges numbers into the lexicographically next greater per ...

  4. UE.getEditor('editor')

    <script type="text/javascript"> $().ready(function(){ var editor = document.getEleme ...

  5. 浅谈压缩感知(二十三):压缩感知重构算法之压缩采样匹配追踪(CoSaMP)

    主要内容: CoSaMP的算法流程 CoSaMP的MATLAB实现 一维信号的实验与结果 测量数M与重构成功概率关系的实验与结果 一.CoSaMP的算法流程 压缩采样匹配追踪(CompressiveS ...

  6. Android进程命令查看

    •       进程 是指一个具有独立功能的程序在某个数据集上的一次动态运行过程,它是系统进行资源分配和调度的最小单元. •       一个进程能够拥有多个线程.每一个线程必须有一个父进程. •   ...

  7. jstl 格式化

    一:JSTL格式化标签又称为I18N标签库,主要用来编写国际化的WEB应用,使用此功能可以对一个特定的语言请求做出合适的处理.例如:中国内地用户将显示简体中文,台湾地区则显示繁体中文,使用I18N格式 ...

  8. Git操作简单入门及相关命令

    说明:本文内容主要来自文末参考链接内容,此文仅作学习记录.如有转载,请到文末参考链接处. 1 基本概念理解 1.1 Git介绍 Git是分布式版本控制系统. 集中式VS分布式,SVN VS Git. ...

  9. CucumberPeople 1.3.2 发布

    CucumberPeople 网站: http://alterhu.github.io/CucumberPeople/ This eclipse plugin based on RubyMine ,a ...

  10. Dockerfile 构建kibana 反向代理应用做用户认证访问

    FROM centos MAINTAINER z*****ch.cn RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime & ...