相信很多人只知道闭包这个词但是具体是怎么回事就不太清楚了,最近在群里有很多小伙伴讨论这个问题但还是蒙眬眬的赶脚。索性就写了这篇文章来帮助大家一起理解闭包。

变量作用域

闭包其实想明白了很简单,但是在理解闭包之前,我们先温习一下作用域的概念不多说 直接上代码来的直接

  • 全局变量
var a = 1;
function f1(){
a++;
console.log(a);
}
f1();//2
f1();//3
  • 局部变量
function f1(){
var a = 1;
a++;
console.log(a);
}
f1();//2
f1();//2

我们大家都知道在函数内部定义的变量(使用var)为局部变量,在函数内部可以访问函数外部的变量和函数,但是在函数外部就访问不了函数内部的变量和函数了

闭包就是能够让我们在函数外部能访问到函数内部的变量和函数下面我们看一个史上最简单的一个闭包,真的不能再简单,你相信我

function f1(){
var str ='我在函数里面,外面的坏人找不到我!!哈哈';
var aa = function(){
alert(str);
}
return aa;
}
var b = f1();
b();

在这个例子中f1中的函数aa 就是一个闭包,什么 aa 不是一个函数么?那闭包也是一个函数咯? 对,闭包说白了 就是一个函数,只不过这个函数比较特殊而已,特殊到什么地方,从例子不难发现 aa 是声明在函数f1 内部的,同时又把这个函数aa当成返回值给return 出来了。然后 我们执行 var b = f1() 就相当于 var b = aa 但是 aa 是在函数内部定义的 通常情况下外部是无法访问的,这个时候我们就把这个函数aa 当成函数的返回值给抛出去,这样在外层就能访问到 aa了 由于 aa 又是在函数f1内部声明的 所以 我们变相的可以访问到函数f1中的变量。这就是闭包最基本的作用

同时它还有很多好处:

  • 希望一个变量长期驻扎在内存中
  • 避免全局变量的污染
  • 私有成员的存在

闭包的特性:

1.函数嵌套函数

2.函数内部可以引用外部的参数和变量

3.参数和变量不会被垃圾回收机制回收

简单的相信大家都能看懂,但是遇见复杂的就蒙蔽的,特别是和对象在一块

就拿今天群里讨论的一个例子来说吧

var sister = '大桃花';
var obj = {
sister:'大妹哒',
sis:function(){
var sister = '小妹哒';
return function(){
console.log(sister);
console.log(this.sister);
};
}
};
function place(){
var sister = '大福晋';
var girl = obj.sis();
girl();
}
place();

在这个例子中 糊弄人的就是 sister 在不同的作用域中都有定义,大兄弟莫慌张!我们一起来揭开它这神秘的面纱,看看到底是大妹哒还是小妹哒,place 调用 place内部声明了一个 sister 然后紧接着 又定义一个 girl = obj.sis();obj的sis方法 的返回值是一个函数 也就是说 girl最后被赋值为一个函数,先不要管这个函数是在哪,反正就是一个函数,然后紧接着girl被调用,再被调用之前 你要明白下面的这些东西函数声明的时候会创建一个作用域链 这个链条上面都有神马东西

  • this
  • 函数内部的变量 --->此函数声明时所在的作用域中的变量 --->....--->window(浏览器中的最顶层)
  • 函数参数(arguments

这3项中其中后两项是在函数声明的时候就被确定下来了,也就是说 函数的作用域链条是在函数声明的时候就确定了,而非是函数调用的时候,然而this 在函数声明是时不确定,而是在函数被调用的时候所确定的,至于怎么确定那就要看函数被调用时所在的对象,函数被调用无非就2中形式:

  • 直接调用(比如 getName()
  • 通过对象.函数的形式调用(比如 obj.getName()

这两种方式调用 第一种的调用方式中 函数中的this 是永远指向 window的(这里抛开 callapply);而第二种调用方式 函数中(这里通常称作方法)的this 是指向点前面的obj

下面我们再看上面的例子

先说 console.log(sister)

由于girl是一个函数的引用 ,而这个函数是在 obj.sis 函数中声明的 只不过是一个匿名函数而已,由于这个匿名函数内部和匿名函数的参数中都没有 sister 这个变量, 所以顺着作用域链往上查找 找到 obj.sis函数的作用中声明了 sister这个变量 找到之后就不再去往上查找(js中的很多机制都是这中情况 比如 原型集成中对象属性的查找规则也类似这样)这个时候 控制台就会输出 obj.sis中定义的 sister变量的值。

再来看 console.log(this.sister)

girl这个函数被调用时的环境 是 place函数内部 而 place 是在整个window作用域下的 所以 这里的this 是指向 window 的 因而 控制台输出结果 会是 window下的 sister

再看下面的例子

var a = 'window';
var sys = {
a:'sys',
getA:function(){
alert(this.a);
},
getAA:function(){
return function(){
alert(this.a);
}
}
}
sys.getA();//sys
sys.getAA()();//window

这个例子中sys.getA() 不用说 大家都能理解,第二个 可以这么来看 先看sys.getAA() 这个结果其实是一个函数你可以把他当成一个函数的名字 a ,变换一下写法 就是 sys.getAA()() 等价于:

var a = sys.getAA();
a();

由于 这是函数的直接调用 所以 这里的this指向 window 最后结果 就是 'window'.

就先说这么多吧 思路可能有点混乱,如果你有什么好的建议或者意见,欢迎指正!

浅谈js闭包的更多相关文章

  1. 浅谈js闭包(closure)

    相信很多从事js开发的朋友都或多或少了解一些有关js闭包(closure)的知识. 本篇文章是从小编个人角度,简单地介绍一下有关js闭包(closure)的相关知识.目的是帮助一些对js开发经验不是很 ...

  2. 浅谈Js闭包现象

    一.1.我们探究这个问题的时候如果按照正常的思维顺序,需要知道闭包是什么它是什么意思,但是这样做会让我们很困惑,了解这个问题我们需要知道它的来源,就是我们为什么要使用闭包,先不管它是什么意思!     ...

  3. 浅谈JS中的闭包

    浅谈JS中的闭包 在介绍闭包之前,我先介绍点JS的基础知识,下面的基础知识会充分的帮助你理解闭包.那么接下来先看下变量的作用域. 变量的作用域 变量共有两种,一种为全局变量,一种为局部变量.那么全局变 ...

  4. 浅谈JS中 var let const 变量声明

    浅谈JS中 var let const 变量声明 用var来声明变量会出现的问题: 1. 允许重复的变量声明:导致数据被覆盖 2. 变量提升:怪异的数据访问.闭包问题 3. 全局变量挂载到全局对象:全 ...

  5. 浅谈JS之AJAX

    0x00:什么是Ajax? Ajax是Asynchronous Javascript And Xml 的缩写(异步javascript及xml),Ajax是使用javascript在浏览器后台操作HT ...

  6. 浅谈 js 正则字面量 与 new RegExp 执行效率

    原文:浅谈 js 正则字面量 与 new RegExp 执行效率 前几天谈了正则匹配 js 字符串的问题:<js 正则学习小记之匹配字符串> 和 <js 正则学习小记之匹配字符串优化 ...

  7. 浅谈 js 字符串之神奇的转义

    原文:浅谈 js 字符串之神奇的转义 字符串在js里是非常常用的,但是你真的了解它么?翻阅<MDN String>就可以了解它的常见用法了,开门见山的就让你了解了字符串是怎么回事. 'st ...

  8. 浅谈 js 正则之 test 方法

    原文:浅谈 js 正则之 test 方法 其实我很少用这个,所以之前一直没注意这个问题,自从落叶那厮写了个变态的测试我才去看了下这东西.先来看个东西吧. var re = /\d/; console. ...

  9. 浅谈 js 数字格式类型

    原文:浅谈 js 数字格式类型 很多人也许只知道 ,123.456,0xff 之类的数字格式.其实 js 格式还有很多数字格式类型,比如 1., .1 这样的,也有 .1e2 这样的. 可能有人说这是 ...

随机推荐

  1. php 字符编码转换函数 iconv mb_convert_encoding比较

    在使用PHP处理字符串时,我们经常会碰到字符编码转换的问题,你碰到过iconv转换失败吗? 发现问题时,网上搜了搜,才发现iconv原来有bug ,碰到一些生僻字就会无法转换,当然了配置第二个参数时, ...

  2. 最近用的几个sql语句

    都在sqlserver数据库下操作,注意sqlserver与mysql和oracle的语法区别 用惯了mysql 和oracle,突然改用sqlserver,有诸多的不习惯,诸多的坑爹,好多的坑,一一 ...

  3. IOS流媒体播放

    IOS流媒体播放   1. 这里的流媒体地址是指服务端那边已经调好格式的可以在ios上播放的视频流. 下面提供几个视频流的地址: NSString *linkStr = http://61.160.2 ...

  4. MTK手机最低亮度值修改教程,有效降低亮度[转]

    感谢halflover的教程 反编译framework-res.apk 打开\framework-res\res\values\integers.xml 然后找到 <integer name=& ...

  5. Sogou搜狗搜索引擎登录网站 - Blog透视镜

    Sogou搜狗是中国搜狐旗下的搜索引擎,其登录方式也很简单,只要输入网址,验证码即可,不需要注册账号,再进行登录,其他非 * 必填的字段,可留下空白不填,验证码只有4码,也很清晰可见,不像有的网站,即 ...

  6. 技巧两种:LINUX删除指定后缀文件及PYTHON更改屏幕字色

    http://blog.csdn.net/caryaliu/article/details/8753028 http://www.iitshare.com/python-print-color-log ...

  7. 例说 AD中ROOM的使用

    从OrCAD中将网表导入之后,区别于从AD原理图中导入,笔者经过反复试验,发现在OrCAD中定义的种种区域属性,比如像Page,Class,Room,在AD中导入之后全部消失,这就意味着你本来按照模块 ...

  8. EXTJS4:在grid中加入合计行

    extjs4很方便的实现简单的合计(针对在不分页的情况下): 它效果实现在:Ext.grid.feature.Summary这个类中 Ext.define('TestResult', { extend ...

  9. Best Cow Line (POJ 3617)

    题目: 给定长度为N的字符串S,要构造一个长度为N的字符串T.起初,T是一个空串,随后反复进行下列任意操作. ·从S的头部删除一个字符,加到T的尾部 ·从S的尾部删除一个字符,加到T的尾部 目标是要构 ...

  10. fdm_search_info_w_book_chain

    数据知识管理平台-元数据管理-fdm_search_info_w_book_chain-详细信息 fdm_search_info_w_book_chain