首页 > 这个是闭包么

这个是闭包么

看到一篇关于闭包的文章javascript的闭包司徒正美的,里面最后有这么一段代码看不懂

var els = document.getElementsByTagName("li");
 
(''+Array(els.length+1)).replace(/./g,function(a,i){
  els[i].onclick=function(){alert(i)}
})

html代码是这个

<ul>
  <li id="a1">aa</li>
  <li id="a2">aa</li>
  <li id="a3">aa</li>
</ul>

是闭包。内部函数捕获了外部函数词法环境中的变量i。

构成闭包的关键是:

具备了这两个条件时,如果Fn引用了外部词法环境中的变量,那么就构成了闭包。

functionwith语句catch语句都是具有独立的词法环境的。所以在这三者内部嵌套了函数后,就有可能构成闭包。不过一般大家说的最多的就是第一种,即函数中套函数的闭包。

更广义的说,实际上全局作用域(window或global)也是一个独立的词法环境,从这一点来说,所有的函数都是闭包。但是由于全局作用域总是处于激活状态的,所以这个结论实际没有多大意义。

至于代码中的new Array那一串东西:就是奇淫异技啊,有炫技的嫌疑。无非就是想生成一个自然数序列,用个for循环来代替也是一样的。总之这段你想弄懂的话当然更好,但是跟闭包没有关系。


这种写法非常诡异,只能说是一种搞怪写法。
给你解释解释,只能听听,正常情况下别这么用。

首先 Array(els.length + 1) 就产生了 li 数量 + 1 个元素的数组,在数组 toString 的过程中,就会形成一个和 li 数量相等长度字符串(Array.toString() 的 格式是 元素逐个打印,元素间 , 逗号分割,由于这个数组元素都为空,所有只输出了中间分割的逗号,逗号的数量时 els.length + 1 再 - 1 刚好时 li 的数量)。
然后用 replace 查找替换,因为匹配条件 /./g 刚好匹配了字符串中的每一个字符,其实也就匹配了 li 的数量那么多次,在匹配回调的过程中,也就把 function(a, i) 执行了 li 的数量那么多次,然后在回调中对每个 li 进行事件绑定。

这种写法非常花哨,看样子是为了展示闭包而写的。


Array(els.length+1) 生成一个长度为 length+1的数组。字符串加数组,会默认调用数组的join,Array是空的,所以会生成length个逗号的字符串。

replace 函数如果第二个是函数,对每一次匹配会调用这个函数,第二个参数 i 是匹配值的偏移,因此依次是 0,1,2....
因此上述代码相当于

function fn(a,i){
  els[i].onclick=function(){alert(i)}
})
fn(',',0);
fn(',',1);
fn(',',2);

如果你懂了闭包,显然这就是个闭包喽

【热门文章】
【热门文章】