对 js 的闭包还是很迷惑?第一个用闭包了吗?

2017-04-03 23:34:37 +08:00
 yantianqi
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <script>
    var lis = document.getElementsByTagName('li');
    for(var i=0; i<lis.length; i++) {
      (function(i) {//这里用闭包了吗?
        lis[i].onclick = function(e) {
          console.log(i);
        }
      })(i)
    }

    for(var i=0; i<5; i++) {
      (function() {
        console.log(i)//输出 0,1,2,3,4
      })()
    }
  </script>
</body>
</html>
4177 次点击
所在节点    程序员
22 条回复
billlee
2017-04-03 23:38:24 +08:00
用闭包的是 })(i) 那一行, function(i) 是函数声明,你写成 function(shit) 也是一样的
billlee
2017-04-03 23:40:36 +08:00
r#1 @billlee 错错错,被你绕晕了,})(i) 也不是闭包,你就是声明了一个函数再立刻调用了
后面那个循环才是闭包
sneezry
2017-04-03 23:50:31 +08:00
不如试试 typescript ,就不用考虑闭包这些琐碎的事情了
zbinlin
2017-04-03 23:59:39 +08:00
第一个注释那里不是闭包,用了传参,而下面的 onclick 那里用了,还有下面第二个也用了
EthanZ
2017-04-04 00:13:30 +08:00
‘用’闭包这个说法不够清楚

楼主给的例子应该是使用了闭包的,但不是闭包的典型用法,可参考

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures

说的很清楚了
luoyaqifei
2017-04-04 00:23:19 +08:00
闭包就是捕获外部函数变量
luoyaqifei
2017-04-04 00:24:47 +08:00
所以第二个 for 里面的函数,没有传参数,但是调用了外部的 for 里的 i ,这就是闭包。
yongSir
2017-04-04 01:23:30 +08:00
所谓闭包就是这样一种函数:
广义上来说,如果一个函数有权访问到了其他函数作用域中的变量,那么就形成了闭包

从这个意义上讲,诸如全局变量的访问,以及内嵌函数对外部函数的访问等等都是闭包
甚至可以推广到任何函数都是闭包,因为都有对全局变量的访问权限, eg :

var a = 1
var foo = function ( console.log(a) )
foo() // 1

但事实上,由于这种访问是自发的天然的作用域链的延伸,所以通常我们并不把对全局变量的访问以及内层对外层的有权访问称之为闭包

我们默认特指的闭包是这样的,比如下面代码:

```javascript
function wrapFoo() {
var wrapVar;
var inner = function() {
console.log(wrapVar)
}

}
```
一个内嵌函数 inner ,具有对其外部函数 wrapFoo 所有变量的使用权,这里就是 warpVar ,如果这时在外部函数的再外层,这里就是全局环境中,实现了对内嵌函数 inner 的调用,这时就称 warpFoo 为闭包,另一个角度来说,外部函数的外面 [这里就是全局环境] ,本身是不能访问 wrapFoo 内部的变量的,通过某种方式 [如借助 return] 实现了对内嵌函数 inner 的调用,这就等于 inner 保存了 warpFoo 的变量,从而让全局中可以被访问到,这就是所谓的 close
bombless
2017-04-04 01:32:01 +08:00
一般是说你打 log 那里访问了非本地又非全局的 i 算是用到了闭包的特性。
yongSir
2017-04-04 01:34:37 +08:00
从 js 的角度来说 如果了解 js 函数的作用域链+全局执行环境和函数执行环境
就是能猜得出闭包
其实是通过单独的`闭包活动对象`完成对其他`[[scop]]`的捕获
从而达到扩展作用域的而实现的


这些在 js 高教中讲得很清楚,建议去翻翻
seeker
2017-04-04 02:23:03 +08:00
匿名函数就是一个闭包。但是一版说闭包是因为这个匿名函数里面引用了外部的变量,也叫自由变量 free variable 。而一般的函数只有参数有影响。比如: function fun(x){return x + y} ,这个函数的 x 是参数而 y 是自由变量,跟函数在定义的时候(而不是实现的时候)的上下文 (context) 的 y 有关的,这个也叫 static scope/lexical scope (与之相对的是 dynamic scope) 。
js 里面 for(var i = 0; i < xxx.length; i++){} 这个循环里面的 i 的作用域不是在 for 里面,而是在 for 外面,所以循环里面有函数引用了这个 i 作为自由变量的时候,可以说使用了闭包。但是就楼主的例子,那个 i 只是作为参数,并不是自由变量,所以就是一般的函数调用。
810913195
2017-04-04 02:56:53 +08:00
闭包最明显的特征:
①函数嵌套定义
②返回内层函数

你两条都不符合。
PythonAnswer
2017-04-04 04:02:57 +08:00
更需要关心的,是,为什么要用闭包?闭包能干啥?
iasi
2017-04-04 07:45:24 +08:00
(function() {
//这是模仿其他语言的块级作用域,跟闭包没关系
})()
闭包简单来说就是在一个函数内部声明一个函数,在内部函数引用外部函数的变量,就可以称为闭包了。

一般还要在内部函数返回这个变量,不然这个闭包就没有意义了。
Mutoo
2017-04-04 08:46:55 +08:00
have you try these:

```
for(var i=0; i<5; i++) {
setTimeout(function() {
console.log(i)
}, 0)
}
```

```
for(var i=0; i<5; i++) {
setTimeout(function(i) {
console.log(i)
}, 0, i)
}
```
Biwood
2017-04-04 09:29:22 +08:00
立即执行函数 ≠ 闭包

闭包不需要你去实现,基本上你定义了一个函数,这个函数在存储状态中就会形成闭包, Chrome 的调试工具甚至可以让你看到函数的闭包里面包含了哪些东西
ryd994
2017-04-04 10:45:21 +08:00
闭包你可以理解为把一部分参数绑上去,得到一个新函数
执行这个新函数就等效为执行原函数,带绑的参数
ipwx
2017-04-04 11:02:08 +08:00
“ In programming languages, closures (also lexical closures or function closures) are techniques for implementing lexically scoped name binding in languages with first-class functions.”

-- https://en.wikipedia.org/wiki/Closure_(computer_programming)

楼上所有的论断都太“主观感受”,不如从这个定义去仔细剖析。
oaix
2017-04-04 12:46:28 +08:00
function(e) {
console.log(i);
}
这个是闭包
(function() {
console.log(i)//输出 0,1,2,3,4
})()
这个也是闭包
wly19960911
2017-04-04 16:52:10 +08:00
其实闭包不重要,重要的是闭包的作用。

闭包函数能把引用外层 function 的参数保留在内存,有一个独特的作用域,就是闭包,一般一层 function 调用全局变量不算,而 function 里面定义 function ,这里才会触发闭包。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/352364

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX