浅谈js闭包
相信很多人只知道闭包这个词但是具体是怎么回事就不太清楚了,最近在群里有很多小伙伴讨论这个问题但还是蒙眬眬的赶脚。索性就写了这篇文章来帮助大家一起理解闭包。
变量作用域
闭包其实想明白了很简单,但是在理解闭包之前,我们先温习一下作用域的概念不多说 直接上代码来的直接
- 全局变量
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的(这里抛开 call和apply);而第二种调用方式 函数中(这里通常称作方法)的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闭包的更多相关文章
- 浅谈js闭包(closure)
相信很多从事js开发的朋友都或多或少了解一些有关js闭包(closure)的知识. 本篇文章是从小编个人角度,简单地介绍一下有关js闭包(closure)的相关知识.目的是帮助一些对js开发经验不是很 ...
- 浅谈Js闭包现象
一.1.我们探究这个问题的时候如果按照正常的思维顺序,需要知道闭包是什么它是什么意思,但是这样做会让我们很困惑,了解这个问题我们需要知道它的来源,就是我们为什么要使用闭包,先不管它是什么意思! ...
- 浅谈JS中的闭包
浅谈JS中的闭包 在介绍闭包之前,我先介绍点JS的基础知识,下面的基础知识会充分的帮助你理解闭包.那么接下来先看下变量的作用域. 变量的作用域 变量共有两种,一种为全局变量,一种为局部变量.那么全局变 ...
- 浅谈JS中 var let const 变量声明
浅谈JS中 var let const 变量声明 用var来声明变量会出现的问题: 1. 允许重复的变量声明:导致数据被覆盖 2. 变量提升:怪异的数据访问.闭包问题 3. 全局变量挂载到全局对象:全 ...
- 浅谈JS之AJAX
0x00:什么是Ajax? Ajax是Asynchronous Javascript And Xml 的缩写(异步javascript及xml),Ajax是使用javascript在浏览器后台操作HT ...
- 浅谈 js 正则字面量 与 new RegExp 执行效率
原文:浅谈 js 正则字面量 与 new RegExp 执行效率 前几天谈了正则匹配 js 字符串的问题:<js 正则学习小记之匹配字符串> 和 <js 正则学习小记之匹配字符串优化 ...
- 浅谈 js 字符串之神奇的转义
原文:浅谈 js 字符串之神奇的转义 字符串在js里是非常常用的,但是你真的了解它么?翻阅<MDN String>就可以了解它的常见用法了,开门见山的就让你了解了字符串是怎么回事. 'st ...
- 浅谈 js 正则之 test 方法
原文:浅谈 js 正则之 test 方法 其实我很少用这个,所以之前一直没注意这个问题,自从落叶那厮写了个变态的测试我才去看了下这东西.先来看个东西吧. var re = /\d/; console. ...
- 浅谈 js 数字格式类型
原文:浅谈 js 数字格式类型 很多人也许只知道 ,123.456,0xff 之类的数字格式.其实 js 格式还有很多数字格式类型,比如 1., .1 这样的,也有 .1e2 这样的. 可能有人说这是 ...
随机推荐
- J2EE学习记录,EJB,JNDI,RMI
Java EE 是java平台企业版(Java Platform Enterprise Edition)缩写,是Sum公司为企业级应用推出的标准平台. 随着Java技术的发展,J2EE平台得到了迅速的 ...
- (原)python中matplotlib的颜色及线条控制
转载请注明出处: http://www.cnblogs.com/darkknightzh/p/6117528.html 参考网址: http://stackoverflow.com/questions ...
- uva 11038 - How Many O's?
想法: 將問題簡化為求1~m 0的總數,以及1~n 0的總數,然後最後再相減. 求1~n 0的總數,要將n分別算每個位數0的個數,舉例如30324: 先從右邊第一位'4'開始,其左邊為3032,表示1 ...
- jquery easyui+layer后台框架
最近使用jquery easyui搭建了一个后台框架,以方便以后使用 上图先: 下载地址:CSDN下载
- php DOMDocument 递归 格式化缩进HTML文档
function format(\DOMNode $node, $treeIndex = 0) { //不格式化的标签 if (in_array($node->nodeName, array(& ...
- Python正则匹配递归获得给出目录下的特定类型的文件小技巧
需求是酱的: 输入一个目录,这个目录包含检测目录的必备信息但不准确需要获得后加工一下,如给出目录:C:\Program Files\Common Files\DESIGNER,需要检测的目录是:C:\ ...
- IIC 概述之2
一.协议 1.空闲状态 I2C总线总线的SDA和SCL两条信号线同时处于高电平时,规定为总线的空闲状态.此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高. ...
- Lintcode--009(单词切分)
http://www.lintcode.com/zh-cn/problem/word-break/ 单词切分 给出一个字符串s和一个词典,判断字符串s是否可以被空格切分成一个或多个出现在字典中的单词. ...
- QT中读取文本数据(txt)
下面的代码实现读取txt文档中的数据,并且是一行一行的读取. void MainWindow::on_pushButton_clicked() { QFile file("abcd.txt& ...
- Oracle RAC 环境下的连接管理
http://blog.csdn.net/cyxlxp8411/article/details/7634003