Javascript闭包——懂不懂由你,反正我是懂了

摘要:“如果你不能向一个六岁的孩子解释清楚,那么其实你自己根本就没弄懂。”好吧,我试着向一个27岁的朋友就是JS闭包(JavaScript closure)却彻底失败了。

  越来越觉得国内没有教书育人的氛围,为了弄懂JS的闭包,我使出了我英语四级吃奶的劲去google上搜寻着有关闭包的解释,当我看到stackoverflow上这一篇解答,我脑中就出现了一句话:就是这货没跑了!

  不才译文见下,见笑了。

  Peter Mortensen问:

就像老Albert所说的,“如果你不能向一个六岁的孩子解释清楚,那么其实你自己根本就没弄懂。”好吧,我试着向一个27岁的朋友就是JS闭包(JavaScript closure)却彻底失败了。

你们会怎么把它解释给一个充满好奇心的六岁孩子听呢?

注:我看过StackOverflow上给出的示例,但根本没用。

  Ali的回答:

  当function里嵌套function时,内部的function可以访问外部function里的变量。

function foo(x) {
    var tmp = 3;
    function bar(y) {
        alert(x + y + (++tmp));
    }
    bar(10);
}
foo(2)

  不管执行多少次,都会alert 16,因为bar能访问foo的参数x,也能访问foo的变量tmp。

  但,这还不是闭包。当你return的是内部function时,就是一个闭包。内部function会close-over外部function的变量直到内部function结束。

function foo(x) {
var tmp = 3;
    return function (y) {
        alert(x + y + (++tmp));
    }
}
var bar = foo(2); // bar 现在是一个闭包
bar(10);

  上面的脚本最终也会alert 16,因为虽然bar不直接处于foo的内部作用域,但bar还是能访问x和tmp。

  但是,由于tmp仍存在于bar闭包的内部,所以它还是会自加1,而且你每次调用bar时它都会自加1.

  (考虑到六岁这个限制:我们其实可以建立不止一个闭包方法,比如return它们的数组,也可以把它们设置为全局变量。它们全都指向相同的x和相同的tmp,而不是各自有一份副本。)

  注:现在来整点儿七岁的内容。

  上面的x是一个字面值(值传递),和JS里其他的字面值一样,当调用foo时,实参x的值被复制了一份,复制的那一份作为了foo的参数x。

  那么问题来了,JS里处理object时是用到引用传递的,那么,你调用foo时传递一个object,foo函数return的闭包也会引用最初那个object!

function foo(x) {
var tmp = 3;
return function (y) {
    alert(x + y + tmp);
    x.memb = x.memb ? x.memb + 1 : 1;
    alert(x.memb);
    }
}
var age = new Number(2);
var bar = foo(age); // bar 现在是一个引用了age的闭包
bar(10);

  不出我们意料,每次运行bar(10),x.memb都会自加1。但需要注意的是x每次都指向同一个object变量——age,运行两次bar(10)后,age.memb会变成2.

  这和HTML对象的内存泄漏有关,呃,不过貌似超出了答题的范围。

  JohnMerlino 对Ali说:

  这里有一个不用return关键字的闭包例子:

function closureExample(objID, text, timedelay) { 
    setTimeout(function() { 
        document.getElementById(objID).innerHTML = text; 
    }, timedelay); 

closureExample(‘myDiv’, ‘Closure is created’, 500);

  深夜1:37 John Pick这样回答:

  JS里的function能访问它们的:

  1. 参数

  2. 局部变量或函数

  3. 外部变量(环境变量?),包括

3.1 全局变量,包括DOM。

3.2 外部函数的变量或函数。

  如果一个函数访问了它的外部变量,那么它就是一个闭包。

  注意,外部函数不是必需的。通过访问外部变量,一个闭包可以维持(keep alive)这些变量。在内部函数和外部函数的例子中,外部函数可以创建局部变量,并且最终退出;但是,如果任何一个或多个内部函数在它退出后却没有退出,那么内部函数就维持了外部函数的局部数据。

  一个典型的例子就是全局变量的使用。

  mykhal这样回答:

  Wikipedia对闭包的定义是这样的:

In computer science, a closure is a function together with a referencing environment for the nonlocal names (free variables) of that function.

  从技术上来讲,在JS中,每个function都是闭包,因为它总是能访问在它外部定义的数据。

  Since scope-defining construction in Javascript is a function, not a code block like in many other languages, what we usually mean by closure in Javascript is a fuction working with nonlocal variables defined in already executed surrounding function.

  闭包经常用于创建含有隐藏数据的函数(但并不总是这样)。

var db = (function() {
// 创建一个隐藏的object, 这个object持有一些数据
// 从外部是不能访问这个object的
var data = {};
// 创建一个函数, 这个函数提供一些访问data的数据的方法
return function(key, val) {
    if (val === undefined) { return data[key] } // get
    else { return data[key] = val } // set
    }
// 我们可以调用这个匿名方法
// 返回这个内部函数,它是一个闭包
})();

db('x'); // 返回 undefined
db('x', 1); // 设置data['x']为1
db('x'); // 返回 1
// 我们不可能访问data这个object本身
// 但是我们可以设置它的成员

  看了这么多外国大牛的解答,不知道你懂还是不懂,反正我是懂了。

  P.S. 发布文章之后看到@xiaotie的一篇文章,觉得有必要推荐一下,因为其剖析得更为深入。有人说应该在文章结尾对闭包进行总结,可惜小弟才疏学浅,不能给出一个精辟的总结。

  @xiaotie对闭包的总结如下:

(1)闭包是一种设计原则,它通过分析上下文,来简化用户的调用,让用户在不知晓的情况下,达到他的目的;

(2)网上主流的对闭包剖析的文章实际上是和闭包原则反向而驰的,如果需要知道闭包细节才能用好的话,这个闭包是设计失败的;

(3)尽量少学习。

  大家学习学习。

转载于:https://www.cnblogs.com/wuyixiaodao/p/5827595.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/256482.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ANSYS——命令流学习(材料属性设置、建模的命令流)

目录 ANSYS基本关键字 命令流的整体结构、每个模块的标识 !文件说明段/BATCH

IOS用CGContextRef画各种图形(文字、圆、直线、弧线、矩形、扇形、椭圆、三角形、圆角矩形、贝塞尔曲线、图片)...

首先了解一下CGContextRef: An opaque type that represents a Quartz 2D drawing environment. Graphics Context是图形上下文,可以将其理解为一块画布,我们可以在上面进行绘画操作,绘制完成后,将画布放到我们的view中显示即可,view看作是一个画框. 自己学习时实现的demo&…

eclipse maven jetty插件方式启动项目

2019独角兽企业重金招聘Python工程师标准>>> 1. 2.点击run即可启动项目 参考:maven命令具体含义请自行百度.例子:maven clean的作用 / maven djetty 转载于:https://my.oschina.net/u/3146772/blog/1576710

AWS S3 Windows系统下的文件夹上传基于python

AWS S3 上传文件,基于cmd命令行发现无法上传文件夹,只能上传单个文件,不知道是我能力不行还是什么原因,如果有大佬了解的可以在下面评论下! 一、环境配置 1.win10 X64; 2.awscli 1.18.91 3.python(程序…

51nod 1004 【快速幂】

思路&#xff1a; 掐住最后一位&#xff0c;快速幂一发就好了 #include<cstdio> #include <map> #include<iostream> #include<string.h> #include<algorithm> using namespace std;typedef __int64 LL;int cal(int g,int x) {int ans1;while(g…

ANSYS——杆单元简介与示例(含新版本2019版本杆实常数设置、ANSYS help的使用、单元列表使用的举例)

目录 杆的一些介绍 问题描述: 求解步骤: 一、设置研究问题为静力学结构问题

Maya 学习资料

罗其胜3d角色强化 CGwhat-Maya变形金刚擎天柱建模教程 Pixar in the box - khan academy Siggraph历届优秀动画 CG软件发展史&#xff1a;MAYA动画十年历程 maya 2014奥迪汽车模型制作教程 &#xff08;yj6k&#xff09; 海贼王路飞建模教程高清全集 转载于:https://www.cnblog…

windows系统环境变量过长解决方案(PATH too long installer unable to modify Path)

在按照官方文档安装PCL库时&#xff0c;发现如下danteng的错误&#xff0c;内心极度崩溃&#xff01;以前也遇到过&#xff0c;当时暂时解决了该问题&#xff0c;现在又遇到了重新解决一次&#xff0c;为了方便以后遇到该问题时不再不知所措&#xff0c;现做个笔记&#xff01;…

jQuery插件-轻量图片轮换-UISlide2

UISlide 的不同效果展现&#xff1a;运行代码 本文转自懒得安分博客园博客&#xff0c;原文链接&#xff1a;XXXXXXXX&#xff0c;如需转载请自行联系原作者

剑指Offer_61_序列化二叉树

题目描述 请实现两个函数&#xff0c;分别用来序列化和反序列化二叉树 解题思路 使用前序遍历&#xff0c;将遇到的结点添加到字符串中&#xff0c;遇到null则将一个#添加要序列化字符串中。反序列化时&#xff0c;每次读取根结点&#xff0c;然后读取其左结点&#xff0c;遇到…

ANSYS——后处理中单元表(ELEMENT table)的作用、创建、使用

目录 单元表的作用 1、访问无法绘制的数据 2、数据的数据源 单元表的创建

久违的反省,容忍现在的自己

距离上一次写的随笔刚好是一个月了&#xff0c;标题还是不知道写什么好&#xff0c;也可以说这一个月来自己能够拿出来称道的东西实在是少之又少吧。更多的感受就是很多时候都是在搬砖&#xff0c;尽管这一个月来学习的东西实事求是地说不是很难的。最大的问题还是解决问题的思…

基于SSL的mysql(MariaDB)主从复制

一、前言 备份数据库是生产环境中的首要任务&#xff0c;重中之重&#xff0c;有时候不得不通过网络进行数据库的复制&#xff0c;这样就需要保证数据在网络传输过程中的安全性&#xff0c;因此使用基于SSL的复制会大加强数据的安全性 二、准备工作 1、主从服务器时间同步 12[r…

ANSYS——分析实例,平面对称问题

目录 一、问题描述 二、问题分析 三、单元类型设置、材料属性设置 四、建模

Ubuntu16.04安装nginx

//ubuntu //安装nginxcurl -LJO http://nginx.org/download/nginx-1.10.1.tar.gz tar zxvf nginx-1.10.1.tar.gz cd nginx-1.10.1.tar.gz sudo apt install gcc autoconf automake build-essential sudo apt-get install libpcre3 libpcre3-dev sudo apt-get install openssl s…

【数据结构作业—02】双链表

2.实现下述要求的Locate运算的函数 问题描述 设有一个带表头结点的双向链表L&#xff0c;每个结点有4个数据成员&#xff1a;指向前驱结点的指针prior、指向后继结点的指针next、存放数据的成员data和访问频度freq。所有结点的freq初始时都为0。每当在链表上进行一次Locate (L,…

ANSYS——对称模型对称边界的确定以及对称边界的约束施加问题

目录 一、什么是对称模型(对称模型的特性)? 二、利用模型的对称特性的目的?

彻底明白Java语言中的IO系统

ava的核心库java.io提供了全面的IO接口&#xff0c;包括&#xff1a;文件读写&#xff0c;标准设备输出等等。Java中IO是以流为基础进行输入输出的&#xff0c;所有数据被串行化写入输出流&#xff0c;或者从输入流读入。在具体使用中很多初学者对Java.io包的使用非常含糊&…

第9章 接口

1、抽象类&#xff1a; 包含抽象方法的类叫抽象类&#xff0c;如果一个类包含一个或多个抽象方法(abstract void f();)&#xff0c;该类必须被限定为抽象的&#xff0c;否则编译出错。 1、抽象类不能被实例化&#xff0c;实例化的工作应该交由它的子类来完成&#xff0c;它只需…

用node-webkit(NW.js)创建桌面程序

以往写windows桌面程序需要用MFC、C#之类的技术&#xff0c;那么如果你只会web开发技术呢&#xff1f;或者说你有一个网站&#xff0c;但是你想把你的网站打包成一个桌面应用程序&#xff0c;该如何做呢&#xff1f; 答案就是用node-webkit这个开源框架&#xff0c;他封装了web…