闭包的初了解
1.什么是闭包?
内部函数能够返回外部函数的作用域(当内部函数返回时,它会携带一个背包,背包中是函数声明时作用域内的所有变量)
我们可以用以下代码来表述以下:
function makeFunc() {
var name = "Mozilla"
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
我们来简单的刨析下上面代码的运行流程
- 编译阶段,变量和函数被声明,作用域即被确定。
- 运行
makeFunc()
,此时会建立makeFunc()
的执行上下文,执行上下文内部储存了makeFunc
声明的所有变量函数信息。 - 函数
makeFunc
运行完毕,此时内部函数displayName
在执行前被返回并且将它的引用赋值给外部的变量myFunc
,此时myFunc
指针指向的还是displayName
,尽管它位于makeFunc
的作用域之外,它还是能够获取makeFunc
的内部变量。 -
myFunc
在外部被执行,displayName
内部可执行代码alert()
,向作用域里请求name
的变量,本地作用域没有找到,就向父级作用域中寻找。
闭包的执行看起来像开发者的一个小小的“作弊手段”,绕过作用域的监管机制,从外部也能获得内部作用域的信息。
2.闭包的用途是什么
闭包的应用,大多数是在需要维护内部变量的场景下
2.1 模拟私有属性
在编程语言中,比如 java
,是支持方法声明为私有的,他们只能被同一类中其他方法所调用,而 javascript
没有这种原生支持,,但我们可以使用闭包来模拟私有方法。
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
}
})();
var Counter1 = makeCounter();
console.log(Counter1.value()); /* logs 0 */
Counter1.increment();
Counter1.increment();
console.log(Counter1.value()); /* logs 2 */
Counter1.decrement();
console.log(Counter1.value()); /* logs 1 */
我们来简单的分析以上代码:
-
makeCounter
函数创建了自己的语法环境,为三个函数共享Counter.increment
,Counter.decrement
和Counter.value
。 - 这个环境包括两个私有量,分别为 p
privateCounter
变量,和一个changeBy
函数,这两项无法从makeCounter
函数外部访问,须通过匿名其返回的三个公共函数访问。 - 这三个公共函数是共享同一个环境的闭包
3. 闭包的缺点
闭包的使用场景非常广泛,那我们是不是可以大量使用闭包呢?不可以,因为闭包过度使用会导致性能问题,我们称他为内存泄露。
例如:在创建新的对象或者类时,方法通常关联到对象的原型,而不是定义到对象的构造器中,原因是当构造器每次被调用时,方法都会被重新赋值一次。
考虑以下实例
function MyObject(name, message) {
this.name = name.toString();
this.message = message.toString();
this.getName = function() {
return this.name;
};
this.getMessage = function() {
return this.message;
};
}
可改写成如下例子
this.name = name.toString();
this.message = message.toString();
}
MyObject.prototype.getName = function() {
return this.name;
};
MyObject.prototype.getMessage = function() {
return this.message;
};
继承的原型为所有对象共享,不必在每次创建对象时,定义方法。
© 著作权归作者所有,转载或内容合作请联系作者
没有回复内容