一直以来,我都以为我已经懂了JavaScript中闭包的概念,直到有一次小伙伴突然问我这个概念的时候,我才发现我根本不知道该怎来么跟他来讲述这个概念。

那时候我就知道我是自我欺骗,打肿脸充胖子了。

所以,花了点时间去专门了解了一下,今天专门记录一下自己所理解的闭包。

一. 概念

闭包,简单来讲,就是定义在函数内部的函数,使用闭包,可以让你有权访问另一个函数作用域内的变量。

所以,想要了解闭包的前提是,你首先要知道在JS中变量作用域的问题。

创建闭包的常见方式就是在函数内部去创建另一个函数:

function fun() {
var variable = 'Hello World';
function inner() {
console.log(variable);
}
return inner;
} var outer = fun();
outer(); // Hello World

在这个例子中,我们想在外部用到`fun()`中定义的`variable`的值,但是因为变量作用域的问题,我们不可能直接取到。

所以我们采取了变通的方法:在fun()函数内部又创建了一个函数inner(),这时fun()内部的variable对于inner()来说是可见的,既然inner()可以取到fun()中的变量,那么我们将inner()返回,就可以用到fun()中定义的variable了。

闭包在此处,就是链接函数内部和外部的一个桥梁。

在这里提一句:如果inner()内部存在新设置的变量,对于fun()函数来说是不可见的,此处涉及到JS中作用链的问题,理解作用链对于彻底理解闭包的问题很有帮助,可以参考JavaScript高级程序设计(第四章)去了解一下作用链。

其实闭包的定义也就这么简单,对于那些过于抽象的定义,置之不理即可,不用强迫自己去理解那些比较晦涩难懂的专业定义,记住自己最终的目的并不是为了咬文嚼字,实用才是根本。

最后借用知乎上一个回答来形象的描述一下闭包的概念:

二. 闭包的用处

我总结的闭包主要用处:

  1. 让外部可以读取函数内部的变量。
  2. 可以封装对象的私有属性和私有方法。

第一点用处就是在说闭包概念时候所举的例子。

下面说下第二点用处:可以封装对象的私有属性和私有方法。

function Worker(name) {
var _salary;
function setSalary(value) {
_salary = value;
}
function getSalary() {
return _salary;
} return {
name: name,
setSalary: setSalary,
getSalary: getSalary
}
} var cxk = Worker('cXK');
cxk.setSalary(100);
cxk.getSalary(); // 100

在上面的代码中,通过闭包,`_salary`变成了`cxk`的私有变量。


# 三. 需要注意的地方

第一点需要注意的地方是关于使用闭包时内存的问题,因为闭包会携带包含它的函数的作用域,因此会比其他的函数占用更多的内存,滥用闭包会造成网页的性能问题,所以对于闭包,建议只在绝对必要时在考虑使用。

对于闭包中垃圾回收的详细测试,参考js闭包测试/司徒正美

第二点需要注意的就是在创建闭包时可能会常犯的错误:在循环中的闭包创建问题。

function createArray() {
var result = [];
for (var i = 0; i < 10; i++) {
result[i] = function () {
return i;
}
}
return result;
} var arr = createArray();
arr[1](); // 10
arr[2](); // 10

可以看到,跟我们预期达到的结果不一样,每一个位置上的函数都返回了10。

这是因为每一个result[i]上都保存着createArray()函数的活动对象(参考JS中的作用链),而给result[i]进行赋值时,'function(){return i}'没有执行,所以最后在arr[1]运行时,返回的i其实都是同一个值,即最后生成的i,值为10。

可以做出如下修改。

修改一:在闭包里再添加一个闭包函数,同时立即执行。

function createArray() {
var result = [];
for (var i = 0; i < 10; i++) {
result[i] = function (num) {
return function () {
return num;
}
}(i)
}
return result;
} var arr = createArray();
arr[1]();

修改二:修改`var`为`let`。


```javascript
function createArray() {
var result = [];
for (let i = 0; i var arr = createArray();

arr1;

<br>
以上就是我对闭包的比较浅显的认知,如果有不对的地方,希望能够指正,以免我误人子弟,谢谢。

关于JS中闭包的问题的更多相关文章

  1. 关于js中闭包的理解

    1.以前很不理解js中闭包的概念及使用,下面来看一下 function foo() { var a = 123; var b = 456; return function () { return a; ...

  2. 彻底搞清js中闭包(Closure)的概念

    js中闭包这个概念对于初学js的同学来说, 会比较陌生, 有些难以理解, 理解起来非常模糊. 今天就和大家一起来探讨一下这个玩意. 相信大家在看完后, 心中的迷惑会迎然而解. 闭包概念: 闭包就是有权 ...

  3. js中闭包和对象相关知识点

    学习js时候,读到几篇不错的博客.http://www.cnblogs.com/yexiaochai/p/3802681.html一,作用域 和C.C++.Java 等常见语言不同,JavaScrip ...

  4. js中闭包的讲解

    一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...

  5. 对js中闭包,作用域,原型的理解

    前几天,和朋友聊天,聊到一些js的基础的时候,有一种‘好像知道,好像又不不知道怎么讲的感觉’...于是捡起书,自己理一理,欢迎拍砖. 闭包 理解闭包首先要理解,js垃圾回收机制,也就是当一个函数被执行 ...

  6. JS中闭包的介绍

    闭包的概念 闭包就是能够读取其他函数内部变量的函数. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascri ...

  7. [学习笔记]JS中闭包的理解

    一.闭包概念的理解 闭包,又称为词法闭包或函数闭包指引用了自由变量的函数.这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外. 自由变量:该变量既不是函数本身定义的也不是函数 ...

  8. JS中闭包、函数与对象的介绍和用法

    闭包 闭包概念:当一个内部函数被调用,就会形成闭包,闭包就是能够读取其他函数内部变量的函数,定义在一个函数内部的函,创建一个闭包环境,让返回的这个子程序抓住i,以便在后续执行时可以保持对这个i的引用. ...

  9. js中闭包来实现bind函数的一段代码的分析

    今天研究了一下bind函数,发现apply和call还可以有这样的妙用,顺便巩固复习了闭包. var first_object = { num: 42 }; var second_object = { ...

随机推荐

  1. Kafka网络模型分析

    Kafka基于高吞吐率和效率考虑,并没有使用第三方网络框架,而且自己基于java nio封装的,总体网络模型如下: Broker的内部按照SEDA模型处理网络请求,处理过程如下: Accept Thr ...

  2. jvm(2)类的初始化(一)

    [深入Java虚拟机]之三:类初始化 类初始化是类加载过程的最后一个阶段,到初始化阶段,才真正开始执行类中的Java程序代码. 1,下面说的初始化主要是类变量的初始化,实例变量的初始化触发条件不同(一 ...

  3. JDK,常见数据结构解读

    一.情有独钟 对数据结构情有独钟,打算慢慢把jdk里的实现都读一遍,发现其中的亮点,持续更新. 二.ArrayList 这应该是我们学习java最早接触的到的数据结构,众所周知,数组在申请了内存之后, ...

  4. Alamofire源码导读一:框架

    源码架构  Alamofire 的源码包括 Core.Extensions.Features.Supporting Files.其中主要逻辑在 Core里. 包括构造请求,发起请求,处理回调等. C ...

  5. day 43 mysql 学习 以及pymysql 学习

    前情提要: 本次主要学习sql 的难点, 多表查询以及连接python  一:多表关联 >多表查询的缺点 二:单表的连表查询[自关联查询] 三:子查询 >主查询 >主查询 >主 ...

  6. c malloc分配内存

    php中的内存分配有用类似emalloc这样的函数,emalloc实际上是C语言中的malloc的一层封装,php启动后,会向OS申请一块内存,可以理解为内存池,以后的php分配内存都是在这块内存池中 ...

  7. POJ 1270

    #include<iostream> #include<algorithm> #define MAXN 26 #define MAX 300 using namespace s ...

  8. 钉钉h5项目实战|仿钉钉聊天|h5移动端钉钉案例

    最近一直着手开发h5仿钉钉项目,使用到了h5+css3+zepto+wcPop2等技术进行开发,实现了消息.表情.动图发送,仿QQ多人拼合图像,可以选择本地图片,并可以图片.视频预览,仿微信发红包及打 ...

  9. redis允许内网访问

    如题有A.B两台服务器. A服务器上装有reis,内网IP:192.168.0.1 B服务器需要访问A服务器上的redis 一.修改A服务器上redis.conf文件 bind 192.168.0.1 ...

  10. 剑指offer三十二之把数组排成最小的数

    一.题目 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323. 二.思路 ( ...