闭包
-
@定义:
有权访问另一个函数的作用域中的变量的函数
-
@创建闭包的常见方式:
在一个函数内部创建另一个函数
-
@作用:
让内部函数可以访问其所在的外部函数声明的参数和变量,即使在外部函数被返回即寿命终结了之后,以及创建块级作用域.
- 利用闭包可以访问外部变量特性,隐藏可以被直接修改的数据,让name变量私有化
function Person(name) {
this.getName = function() {
return name;
}
this.setName = function(value) {
name = value;
}
}
let person = new Person("kobe")
console.log(person.getName()) //kobe
person.setName("james")
console.log(person.getName()) //james
getName()和SetName()能作为闭包访问name变量,除了Person生成的对象可以通过这两个特权函数访问和修改name变量,其他没有办法访问。
- 创建块级别作用域.
function outputNumbers1(num) {
//块级作用域
(function() {
for (var i = 0; i < num; i++) {
console.log(i); // 0, 1, ... num - 1
}
})()
console.log(i); //Uncaught ReferenceError: i is not defined
}
outputNumbers1(10);
闭包的内存泄露详细讲解将在作用域篇讲解。
-
@缺点:闭包会使函数中的变量(无论有没有用)一直保存在内存中,出现内存泄露(内存消耗很大的情况下影响网页性能)
function(){
var element = document.getElementById("id");
element.onclick = function(){
........
alert(element.id);
}
}
匿名函数存在着对element的引用,匿名函数只要存在,element的引用计数就一直为1,就永远不会被内存回收。
所以不能滥用闭包,解决办法是,退出函数之前,将不使用的局部变量删除。简单的说就是把那些不需要的变量,但是垃圾回收又收不走的的那些赋值为null,然后让垃圾回收走,
解决方法为
function(){
var el = document.getElementById("id");
var id = el.id; //解除循环引用
el.onclick = function(){
alert(id);
}
el = null; // 将闭包引用的外部函数中活动对象清除
}