闭包closure
- 一、引例
- 1、n++函数
- 2、把n放外面
- 3、改成闭包
- 二、例子
- 1、点击按钮增加
- 2、li绑定事件
- 三、关闭
一、引例
1、n++函数
function closure() {
let n=1
n++
console.log(n);
}
closure() //2
closure() //2
closure() //2
closure() //2
2、把n放外面
let n=1
function closure() {
n++
console.log(n);
}
closure() //2
closure() //3
closure() //4
closure() //5
把n放外面,成为全局变量,缺点是会影响全局
3、改成闭包
function closure() {
let n=1
function child() {
n++
}
console.log(n);
}
let myClosure=closure() // 接收closure返回值
console.log(myClosure); // undefined
function closure() {
let n=1
function child() {
n++
console.log(n);
}
}
closure() //无返回
closure() //无返回
closure() //无返回
执行了closure() ,但是里面的child()不执行,这种写法不知道什么意思?
function closure() {
let n=1
return function child() {
n++
console.log(n);
}
}
let myClosure=closure() // 接收closure返回值
console.log(myClosure);
//myClosure 返回 ƒ child() {
n++
console.log(n);
}
再执行myClosure()
function closure() {
let n=1
return function child() {
n++
console.log(n);
}
}
let myClosure=closure()
myClosure() //2
myClosure() //3
myClosure() //4
n的值被保存在内存中,保存在该js内存里面开辟的小块新内存中,等于该js文件内存里可以开辟更多的内存空间,互不影响独立的空间。感觉是在网页内引入多个js文件的child版本
二、例子
1、点击按钮增加
知乎上看到的这个例子https://www.zhihu.com/question/19554716
<body>
<button id="add">加1</button>
<span id="span">1</span>
<script>
(function (){
var val = 1;
add.onclick = function (){
val++;
span.innerHTML = val;
}
})() // 自执行匿名函数
</script>
</body>
(1)例子中,去掉自执行匿名函数,也是正常运行的,只不过val变成全局变量
(2)获取dom元素不是let add=document.getElementById(‘add’),然后再add.onclick?
<button id="add">加1</button>
<span id="span">1</span>
<script>
console.log(add); // <button id="add">加1</button>
var val = 1;
add.onclick = function (){
val++;
span.innerHTML = val;
}
</script>
在Chrome的JavaScript终端中,你只需要输入一个元素的ID,就可以访问到这个元素?
https://www.cnblogs.com/jiangxiaobo/p/6061745.html
2、li绑定事件
https://zhuanlan.zhihu.com/p/87950150
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
let li=document.getElementsByTagName('li')
li.forEach(element => {
console.log(element); //forEach不遍历类数组 //li.forEach = Array.prototype.forEach;
});
</script>
<script>
let li=document.getElementsByTagName('li')
for(let ele of li){
console.log(ele); //for of可以遍历数组/类数组/字符串/Set和Map
}
</script>
打印li内容
let li=document.getElementsByTagName('li')
for(let ele of li){
ele.onclick=()=>{
console.log(ele.innerHTML); // 点击li可以打印li的内容
}
}
打印li的索引
<script>
let li=document.getElementsByTagName('li')
for (let i = 0; i < li.length; i++) {
li[i].onclick=()=>{
console.log(i);
}
}
</script> // 可以正常打印索引
当我把let i改为var i 后
<script>
let li=document.getElementsByTagName('li')
for (var i = 0; i < li.length; i++) {
li[i].onclick=()=>{
console.log(i);
}
}
</script> // 点击li打印的i都为5
为什么?为什么?为什么?
<script>
let li=document.getElementsByTagName('li')
for (var i = 0; i < li.length; i++) {
li[i].onclick=()=>{
console.log(i);
}
}
li[0].onclick() //5 //吃惊
</script>
for循环结束后,i的值为5,每个li点击事件console.log(i)中的i都为5
<script>
let li=document.getElementsByTagName('li')
for (var i = 0; i < li.length; i++) {
li[i].onclick=()=>{
console.log(i);
}
}
console.log(i); //5
li[0].onclick() //5
</script>
改为let
<script>
let li=document.getElementsByTagName('li')
for (let i = 0; i < li.length; i++) {
li[i].onclick=()=>{
console.log(i);
}
}
console.log(i); // 报错,i未定义
li[0].onclick()
</script>
<script>
let li=document.getElementsByTagName('li')
for (let i = 0; i < li.length; i++) {
li[i].onclick=()=>{
console.log(i);
}
}
// console.log(i);
li[0].onclick() //0
</script>
在var下的for循环,相当于
<script>
let li=document.getElementsByTagName('li')
{
var i=0
li[i].onclick=()=>{
console.log(i);
}
}
{
var i=1
li[i].onclick=()=>{
console.log(i);
}
}
{
var i=2
li[i].onclick=()=>{
console.log(i);
}
}
</script>
而let是有作用域的,相当于有了个闭包?
把var包装成闭包,例子,不知道实用不,let不是可以很好解决吗?
<script>
let li=document.getElementsByTagName('li')
for (var i = 0; i < li.length; i++) {
li[i].onclick=function(i){
return ()=> {
console.log(i);
}
}(i)
}
</script>
三、关闭
function closure() {
let n = 1;
return function child() {
n++;
console.log(n);
};
}
let myClosure = closure();
myClosure(); //2
myClosure(); //3
myClosure(); //4
myClosure=null // 关闭
myClosure = closure(); // 打开
myClosure(); //2