闭包就是一个函数可以访问另外一个函数内部的变量。函数内部的变量很明显是一个局部变量。
在JS中,我们所定义的任意一个函数,都可以看作是闭包。只不过最明显的存在与嵌套关系的函数中,内部的子函数 可以 访问父函数 中的变量。
但是,我们想要从父函数的外部访问其内部的局部变量,该怎么实现?
通过观察,发现子函数可以访问父函数的局部变量,所以我们尝试着让这个内部的子函数作为桥梁连通内外,让外部有能力去访问一个函数内部的变量。
for(var i = 0; i < 10; i++){ //一个函数就是一个闭包 (function(j){ setTimeout(function () { console.log("i:",j); },1000); })(i); }
上面的代码 :内层定时器函数引用外层IIFE传的值形成闭包。
setTimout作外层函数,setTimeout的第一个回调函数作内层函数,内层引用外层的参数形成闭包。
例如:点击页面li中的内容,弹出 "您点击了第 N 条内容"
写在最前面: 这里声明的变量都是使用var, 如果使用es6新增的let关键字 则可以正常访问。
因为var是用来定义函数级作用域变量的,并且不能存储数据;
let关键字是定义块级作用域变量的,可以存储数据。
例如:
let lis = document.querySelectorAll('li'); for(let i = 0; i < lis.length; i++) { lis[i].onclick = function() { alert('您点击了第' + Number(i + 1) + '条内容') } }
以下三种方法讨论使用var声明如何解决:
第一种方法:
利用this,对应索引的方法
for(var i = 0; i < lis.length; i++) { lis[i].index = i; lis[i].onclick = function() { console.log(this.index) alert('您点击了第' + Number(this.index + 1) + '条内容') } }
第二种方法:
利用闭包
for(var i = 0; i < lis.length; i++) { (function(j) { lis[j].onclick = function() { alert('您点击了第' + Number(j + 1) + '条内容') } })(i) }
第三种方法:
利用事件委托
事件委托:
借助事件冒泡的原理,用父元素去处理子元素中具有相同的事件。这样可以减少DOM的操作。
事件委托优点:
1.减少事件数量;2.避免内存外泄;3.预言未来元素
// list为ul标签的id let list = document.getElementById('list'); for(var i = 0; i < lis.length; i++) { // 为每一个li标签添加自定义属性 lis[i].setAttribute('data-index', i) } list.onclick = function(e) { var t = e.target || e.srcElement; alert('您点击了第' + (Number(t.getAttribute('data-index'))+1) + '条内容') }