Skip to main content

Javascript教程第九章:闭包与作用域

Javascript教程第九章:闭包与作用域

一.闭包与作用域

1.延伸函数环境生命周期

在作用域中,只要有一个东西被调用,那么其他的与其共存

function hd(){
let n = 1;
return function show(){
console.log(++n);
}
}
hd()(); //返回2
hd()(); //返回2

观察上面的例子,在hd被调用了俩次后,n并没有自加并被保存,原因是当我们调用一个函数的时候,js会创建出新的作用域,而在每一个新的作用域当中,n的初始值都为1,自加后的结果并没有被保存

function hd(){
let n = 1;
return function show(){
console.log(++n);
}
}
let a = hd()
a() //2
a() //3

此时我们将hd函数赋值给a,再重复调用的时候,输出结果为2和3,说明当前作用域被保存了

只要函数被外部引用,则环境不会被删除(公园要有人用)

2.构造函数中作用域的使用形态

function hd(){
let n = 1;
this.sum = function(){
console.log(++n);
}
}
let a = new hd();
a.sum();
a.sum();

我们可以将this想象为一个{},当我们通过a调用hd中的sum方法时,函数hd被外部调用,n的值自然被保存了下来,所以重复调用的时候,n进行自加

3.块级作用域

由于var是在块级作用域之前创造的,所有var没用块级作用域(但是是有函数作用域的),而let和const都有块级作用域

{
let a = 1;
}
{
var a = 2; //被提升到window
}

console.log(a); //2

4.什么是闭包

一个函数可以访问到其他函数中的属性

5.闭包的内存泄露的解决方法

<div data_desc = "houdunren">后盾人</div>
<div data_desc = "hdcms">后盾人-css</div>

我们要给div添加点击事件,点击的时候弹出data_desc的文字

let divs = document.querySelectAll("div");
divs.forEach(function(item){
item.addEventListener("click",function(){
console.log(item.getAttribute("data_desc"));
})
})

此时由于闭包的特性,我们在click的回调函数中调用了外部函数的item,所以将所有的div元素都保存了起来,极大的浪费了内存,此时我们可以这样做

let divs = document.querySelectAll("div");
divs.forEach(function(item){
let desc = item.getAttribute("data_desc");
item.addEventListener("click",function(){
console.log(desc);
})
item = null;
})