您的位置:首页 > Web前端 > JavaScript

JavaScript闭包

2016-03-28 20:08 447 查看

啥是闭包

大神是这么说的

闭包就是能够读取其他函数内部变量的函数。

阮一峰

所以从本质上说,闭包是个名词(以前以为是动词),它指的是一个能为外部函数提供父函数私有变量的函数,听起来有点绕,不如用代码解释吧。

function a() {
var value = 1

function b() {
console.log(value)
}

return b
}
var c = a()
c()//输出1


c访问到了a的私有变量value

闭包产生的原因

作用域

要理解闭包,首先必须理解Javascript特殊的变量作用域。

变量的作用域无非就是两种:全局变量和局部变量。

Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。另一方面,在函数外部自然无法读取函数内的局部变量。

闭包是怎么保存变量的?

语法域位于某个特定的区域,具有持续参照(读写)位于该区域内自身范围之外的执行域上的非持久型变量值能力的段落。这些外部执行域的非持久型变量神奇地保留它们在闭包最初定义(或创建)时的值(深连结)。

简单来说,Javascript闭包就是在另一个作用域中保存了一份它从上一级函数或作用域取得的变量(键值对),而这些键值对是不会随上一级函数的执行完成而销毁。周爱民说得更清楚,闭包就是“属性表”,闭包就是一个数据块,闭包就是一个存放着“Name=Value”的对照表。就这么简单。但是,必须强调,闭包是运行期概念,一个函数实例。

上面这段话,大概意思可以粗略理解为:子函数保存了父函数的键值对数据块儿。即使父函数已经运行完并被销毁了,仍然可以通过子函数访问它的数据。

闭包的用途

闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中(隐隐地觉察到了内存泄漏问题,以后再研究)。

闭包可以干啥

JavaScript的很多高级特性都依赖闭包实现–阮一峰

╮(╯_╰)╭ 一个初学者,还看不到这样的高级实例,只好拿一个最简单的栗子来解释下。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</body>
</html>


要求是给li标签循环绑定事件,alert绑定的序号

初学者会这样写

var arry = document.getElementsByTagName('li')
for (var i = 0; i < 3; i++) {
arry[i].onclick=function(){
alert(i)
}
}


这样写不管怎么点,提示的都是3。因为函数在运行时根本就没保存i的值而此时提示的i已经变成3了。所以我们需要保存运行时i的值,这就是闭包的一个典型使用场景。知道了问题的所在就尝试去解决吧。

错误写法

//错误写法
//要用内部函数去保存外部的变量是吧?好,这么写可不可以
var arry = document.getElementsByTagName('li')
for (var i = 0; i < 3; i++) {
arry[i].onclick=function(){
var i=i//你看,我保存了变量i哦
alert(i)
}
}


抱歉,不可以。为啥呢?虽然你在函数内写了赋值语句,本意是去保存这个变量。但是这个赋值语句是在点击时才执行,也就是说,函数上下文早就不在for循环里了。

//嗯 其实上面那个就是我的想法

正确写法

不要被上面的写法误导了,看下正确的写法是怎么做的。

//第一种写法
var arry = document.getElementsByTagName('li')
for (var i = 0; i < 3; i++) {
(function (i) {
arry[i].onclick = function () {
alert(i)
}
})(i)
}


是不是看不懂?为啥要给匿名函数加(),后面那个(i)又是干嘛的?

()()

这两个括号其实就是让这个匿名函数强制执行。用()把这个函数包裹起来然后传入参数i。里面子函数虽然没有执行,但是它的运行环境已经在一个函数内部,并且持有了外部函数的变量i。这就是一个闭包的简单应用
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: