产生闭包的条件
概念:闭包是由函数以及创造该函数的语法环境结合组成。
这个环境包含了这个闭包创建时所能访问的所有局部变量。
- 嵌套结构的函数
- 内部函数访问外部函数的变量
- 在外部函数的外面调用内部函数
// 普通情况
function fn(){
var a = 1;
function e(){
a++;
console.log('普通函数'+a);
}
e();
}
fn();
// 闭包
function fn(){
var a = 1;
function e(){
a++;
console.log(a);
}
return e;
}
var e = fn();
e();
//不用返回值
var fn1;
var fn2;
function fn(){
var a = 1;
fn1 = function e(){
a++;
console.log(a);
}
fn2 = function(){
a--;
console.log(a);
}
}
fn();
fn1();
闭包的特性
简易类的特性:闭包工厂(函数)产生新的闭包对象。
简易类的特性:
//闭包函数
function fn(){
var a = 1;
function e(){
a++;
console.log(a);
}
return e;
}
//闭包对象 2个闭包对象互不干扰
var fn1 = fn();
var fn2 = fn();
fn1();
fn1();
fn1();//fn1 a已经是4
fn2();//fn2 a还是2 二者互不干扰,相当于以及简易类, 创建的是一个新的闭包对象
循环中使用变量的解决方法
- 使用立即执行函数
- 使用多个闭包函数
- 使用let const 块级作用域
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
//循环中绑定点击事件 有嵌套函数,本质也是一个闭包,只是它只创建了一个闭包对象:最后i = 5;
// 点击事件函数使用 i 使用了外部函数变量。点击的时候window对象使用点击事件函数。
function setClick(){
var oli = document.getElementsByTagName('li');
for(var i = 0; i < oli.length; i++){
oli[i].onclick = function(){
show(i);
}
}
}
setClick();
function show(id){
console.log('li'+id);
}
//使用多个闭包函数
function setClick(){
var oli = document.getElementsByTagName('li');
for(var i = 0; i < oli.length; i++){
oli[i].onclick = show(i);
}
}
function show(id){
return function(){
console.log('li'+id);
}
}
setClick();
//使用立即执行函数
function setClick(){
var oli = document.getElementsByTagName('li');
for(var i = 0; i < oli.length; i++){
(function(j){
oli[j].onclick = function(){
console.log(j);
}
})(i)
}
}
setClick();
// 使用let块级作用域特点
闭包的作用
- 让局部变量变成私有化的长存变量
- 给事件调用函数传递参数