这两天在研究闭包,网上一通找,有牛人写的帖子,有普通人写的帖子,但是大多没戳中本小白所纠结的点,而且大多插入了立即执行函数,其实根本不需要的,反而让人产生了误解。这里我用我的方式讲解一下闭包。

1.目的:保证局部变量常驻在内存中,且只能通过固定的方式访问,不可以被所有人访问,算起来也算是个只能被指定对象访问的专用型全局变量。

2.实现方式:在函数f1中返回一个内部定义的函数f2,后通过使用返回出来的函数f2来操作f1中定义的局部变量。

下面我来从各种刁钻的角度来举例详细说明,包学包会!看完例子以后再看上面说的目的和实现方式就会有种豁然开朗的感觉了!

round 1:

function add() {
  var x = 0;
  return function () {
    return ++x;
  }
}; /*此处的add()的括号和function add()的括号表达的意思是完全不同的, 在此处add表示上
面定义的函数,add()表示执行一次上面定义的函 数,这一点很关键!执行一次的结果就是返回了函数 function () {return ++x;},但是请注意!这里返回的仅仅是函数本 身,也就是此时函数尚未执行,故此时x=0*/
var temp=add(); //执行一次返回的函数,++x,此时x=1
temp(); //再次执行一次返回的函数,此时x=2,且输出了函数的返回值2,可以在控制台中看到
console.log(temp());

这就完成了闭包了,add函数中的x常驻内存,且我可以在add函数外部通过调用它返回的函数来操作这个x,如果看懂了下面可以不看,如果看了其他帖子有一些其他的异或比如立即执行函数之类的可以看看下面的,你很快就不会疑惑了!

round 2:

//此处temp表示函数add函数本身,但是尚未执行。

var temp = function add() {
  var x = 0;
  return function () {
    return ++x;
  }
}; //执行temp函数,返回函数 function () {return ++x;},但尚未执行该函数,故x=0
var temp1 = temp(); //执行temp1,此时执行了一次function () {return ++x;},故x=1
temp1(); //再次执行一次function () {return ++x;},此时x=2,且输出到了控制台
console.log(temp1());

这一回合是为下面的立即执行函数做铺垫,下面立即执行函数版本隆重登场!当当当当!

round 3:

/*仔细看,此处为(fucntion add(){})(),此处执行了立即执行函数,也就是说返回给temp的与round2返回的add函数本身不同,而是返回的 function () {return ++x;}*/

var temp = (function add() {
  var x = 0;
  return function () {
    return ++x;
  }
  })(); //顺理成章的,这里直接执行temp,就是执行了function () {return ++x;},故x=1
temp(); //同理x=2
console.log(temp());

经过上面三个例子的讲解想必你已经心中有数了,但是肯定还是存在疑惑的,比如说round1中var temp=add();,我不把add()的结果赋给temp直接执行行不行?答案是否定的,有一点一定要认知清楚,函数是对象,这一点至关重要,否则将会走入误区。下面举例说明:

这个是round1的改版:

function add() {
  var x = 0;
  return function () {
    return ++x;
  }
}; console.log(add()());//输出1 console.log(add()());//输出1

为什么会这样呢?关键点在于函数是对象,上面实行了两次add()(),在这两次中,add()返回的对象是不一样的,所以他们各自再执行add()()就是为各自的局部变量x加1,所以才两次都输出1,假如改一下

function add() {
var x = 0;
return function () {
return ++x;
}
}; var temp1 = add();
var temp2 = add();
console.log(temp1());//输出1
console.log(temp1());//输出2 console.log(temp2());//输出1
console.log(temp2());//输出2

这样是不是就明白了,同理add函数也不能写成下面这种形式:

function add() {
  var x = 0;
  return (function () {
    return ++x;
  })()
};

否则返回的只是一个常量而不是一个对象了。希望这篇文章能给跟我一样在摸索闭包的小白一点启发,嘿嘿嘿

关于javascript闭包的最通俗易懂的理解的更多相关文章

  1. 深入理解javascript闭包(一)

    闭包(closure)是Javascript语言的一个难点.也是它的特色,非常多高级应用都要依靠闭包实现. 一.什么是闭包? 官方"的解释是:闭包是一个拥有很多变量和绑定了这些变量的环境的表 ...

  2. javascript 闭包(转)

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

  3. JavaScript 闭包整合

    初遇闭包感觉很困惑,上网查看了些许介绍,有很多没看懂,就想先对能懂的东西整整 首先觉得要了解闭包,要先对一.JavaScript的变量作用域和作用域链有基本了解 1.变量的作用域分为:全局变量和局部变 ...

  4. 一篇文章图文并茂地带你轻松学完 JavaScript 闭包

    JavaScript 闭包 为了更好地理解 JavaScript 闭包,笔者将先从 JavaScript 执行上下文以及 JavaScript 作用域开始写起,如果读者对这方面已经了解了,可以直接跳过 ...

  5. JavaScript学习总结——我所理解的JavaScript闭包

    一.闭包(Closure) 1.1.什么是闭包? 理解闭包概念: a.闭包是指有权限访问另一个函数作用域的变量的函数,创建闭包的常见方式就是在一个函数内部创建另一个函数,也就是创建一个内部函数,创建一 ...

  6. JavaScript闭包理解【关键字:普通函数、闭包、解决获取元素标签索引】

    以前总觉得闭包很抽象,很难理解,所以百度一下"闭包"概览,百度的解释是:“闭包是指可以包含自由(未绑定到特定对象)变量的代码块:这些变量不是在这个代码块内或者任何全局上下文中定义的 ...

  7. javascript闭包理解

    //闭包理解一 function superFun(){ var _super_a='a'; function subfuc(){ console.log(_super_a); } return su ...

  8. javascript 闭包最简单理解

    首先说3点与闭包有关系的东西. 一.变量的作用域 变量的作用域不难理解. 1.函数内部可以访问函数外部的变量,而函数外部不能访问函数内部的变量. 2.如果在函数内定义变量的时候,不加var,那么是全局 ...

  9. 全面理解Javascript闭包和闭包的几种写法及用途

    好久没有写博客了,过了一个十一长假都变懒了,今天总算是恢复状态了.好了,进入正题,今天来说一说javascript里面的闭包吧!本篇博客主要讲一些实用的东西,主要将闭包的写法.用法和用途.  一.什么 ...

随机推荐

  1. 环境搭建-ELK单节点环境搭建(02)

    写在前面 常说:"工欲善其事必先利其器",这话想想也是一点毛病也没有,在开始学习任何技术之前,我们总得有一个实际可供操作的实验环境.有人说,"看十遍不如用一遍" ...

  2. Spring boot 梳理 - 模版引擎 -freemarker

    开发环境中关闭缓存 spring: thymeleaf: cache: false freemarker: cache: false Spring boot 集成 freemarker <dep ...

  3. .Net Core 商城微服务项目系列(六):搭建自己的Nuget包服务器

    当我们使用微服务架构之后,紧接而来的问题便是服务之间的程序集引用问题,可能没接触过的同学不太理解这句话,都已经微服务化了为什么还要互相引用程序集,当然可以不引用.但是我们会有这样一种情况,我们的每个接 ...

  4. mysql root密码忘记

    首先停掉mysql服务,在/etc/my.cnf中添加 skip-grant-tables,同时可以添加skip-networking选项来禁用网络功能,防止这时其他人通过网络连接到数据库 [mysq ...

  5. 【博客美化】添加github图标

    <a href="https://github.com/cai3231" target="_blank"> <img style=" ...

  6. 地图的折线:Polyline

    (1)var polyline = new BMap.Polyline([new BMap.Point(X1,Y1),new BMap.Point(X2,Y2),new BMap.Point(X3,Y ...

  7. linux无法安装应用

    需安装flex 和bison 一般需要更新软件源 root权限 下 apt-get update apt-get upgrade 如果出现以下问题,先查看网络是否畅通: ping 192.168.0. ...

  8. uni-app h5端跳转到底部导航栏的时候使用方法uni.switchTab跳转刷新页面更新数据

    h5端的uni-app项目 需求:uni-app h5端跳转到底部导航栏的时候使用方法uni.switchTab跳转刷新页面更新数据 百度的方法如下: uni.switchTab({ url: '/p ...

  9. ubuntu14.04 安装tensorflow始末

    基于ubuntu14.04 干净的系统一步步遇到的坑记录下来: 怀着平静学习的心情,问题总的能解决的! 1. 首先看了下当前python版本 python --version Python 2.7.6 ...

  10. 彻底修改eclipse中项目的名称

    需要四个步骤: 一.右键工程:Refactor->Rename,或选中工程按F2,修改名称 二.修改项目目录下:.project文件 三.项目右键属性 --> Web Project Se ...