javascript闭包理解(Closure)
还记得上学那会儿同学问我学了这么久的javascript,知道什么是闭包吗?然后就云里雾里的给我讲了一通。后来也遇到了一些关于闭包的东西,现在用一些具体的实例来具体陈述下关于闭包的理解。
闭包
什么是闭包,其实最通俗的解释就是指函数有*独立的变量。换句话说,定义在闭包中的函数可以“记忆”它创建时候的环境。
变量的作用域
大家都知道,在javascript中变量分为局部变量和全局变量。
在javascript中函数内部可以直接访问全局变量,这也是其语言的独特之处。
var foo = 123;
function fn(){
console.log(foo);
}
fn(); //123
当然在全局环境下不能访问函数内部的局部变量,如下
function fn(){
var foo = 123;
}
console.log(foo); //error
以上就是javascript中局部变量与全局变量的一个比较。在javascript中如果没有用var关键字申明一个变量的话,那在引用的时候会默认为全局变量。
计数器
下面来看看闭包的一个实例加深理解。
有时候我们在程序中会用到计数器来记录特顶的值,当然我们可以这样。
var counter = 0;
function increment() {
counter = counter + 1;
console.log(counter);
}
当用到多个计数器的时候,可能会这样
var counter1 = 0;
function increment1() {
counter1 = counter1 + 1;
console.log(counter1);
}
var counter2 = 0;
function increment2() {
counter2 = counter2 + 1;
console.log(counter2);
}
每次用到的时候调用一次increment,在遇到多个计数器时,就会定义多个变量多个函数进行记录。但是这样就出现了过多的冗余,我们想要的是就用一个变量记录就可以了。
闭包实现
function createCounter() {
var counter = 0;
function increment() {
counter = counter + 1;
console.log(counter);
}
return increment;
}
var counter1 = creatCounter();
var counter2 = creatCounter();
counter1()//1
counter1()//2
counter2()//1
counter2()//2
这样是不是就清晰简洁得多了,这个有点像类的实例化,但是javascript又没有类这个概念。其实通过闭包就可以实现通常的面向对象的类的实现。
用闭包模拟私有方法
下面的示例展现了如何使用闭包来定义公共函数,且其可以访问私有函数和变量。
var Person = function(){
var _age = 0;
function changeAge(val){
_age += val;
}
return {
agePlus: function() {
changeAge(1);
},
ageSub: function() {
changeAge(-1);
},
print: function() {
return _age;
}
}
}
var person1 = Person();
var person2 = Person();
console.log(person1.print()); //0
person1.agePlus();
person1.agePlus();
console.log(person1.print()); //2
person1.ageSub();
console.log(person1.print()); //1
console.log(person2.print()); //0
上面只是用闭包实现的一个很粗糙的一个类构造。person1,person2都是Person类的一个实例,Person是一个简单的类,其中有_age私有成员和changeAge私有函数。其他的都是共有函数,可以供实例对象访问的。
结语
闭包是编程语言一个很棒的属性。当我们想在 JavaScript 创建“真正的”隐藏域,或者需要创建简单的构造器时,闭包这个属性是非常好用的。在多人合作的团队中用闭包实现一个模块的复用也是一个不错的选择。