js闭包的理解
什么是闭包
通俗的来讲,个人觉得闭包就是延长变量作用域的函数。
众所周知js的作用域分为全局作用域和链式作用域。在函数外部无法访问函数内部的变量,但有些时候我们需要访问函数内部变量,为了达到这个目的,闭包就成了很好的解决方案。可以看一个小例子:
initEvent : function(){
var self = this;
var countFunction = self.countIncrement();
$('#selector').on('click',function(){
//do something
// 用来记录当前按钮点击次数
countFunction();
});
}
function countIncrement(){
var count = 0;
return function(){
return count++;
}
}
上述代码是为了记录某按钮点击次数,其中countIncrement方法即为闭包,在方法内部声明了变量count,而在外部按钮点击是获取。虽然将count变量声明为全局变量可达到实现同样的效果,但这样做可以避免对全局变量的污染,代码可读性更高。也会避免因为时间问题导致回头翻看代码时不知道count变量代表的含义。
闭包的用处
个人认为闭包的用处主要有两种情况,分别是某些仅需要运行一次的代码,例如初始化。另外一种则是模拟面向对象语言中的封装型。若各位大神觉得有遗漏,欢迎指出,共同学习!
某些只需要运行一次的代码
在某些情况下可能存在一部分逻辑仅需要处理一次,这种情况下可以使用闭包来处理,在运行结束后释放资源。例如做一些初始化操作,如上个例子中count属性,仅需要初始化一次。再看一个复杂的例子。示例如下:
var datamodel = {
table : [],
tree : {}
};
(function(dm){
for ( var i = 0; i < 10; i++){
dm.table.push(i);
}
dm.tree.count = dm.table.length;
})(datamodel)
** 注意:这种做法影响到了全局变量datamodel! **
从此可以看出当前的用法有点类似java中静态代码块的作用。具体情况还需要继续研究分析。
实现封装性
由于javascript不是面向对象的语言,无法完美实现封装性。但使用闭包可以达到一样的效果,实现private的属性,示例如下:
function Student(){
var name;
var num;
}
var s1 = new Student();
s1.name = '1';
s1.num = '2';
从上面例子可以看出,当前s1对象有两个属性,任何人都可以随时修改,若想要实现只读,或私有变量,则需要借助闭包来实现,示例如下:
function student1(){
var name;
var num;
return {
getName : function(){
return name;
},
setName : function(name){
name = name;
}
}
}
var s2 = student1();
s2.name; // --- undefined
s2.num; // --- undefined
s2.setName('1');
s2.getName(); // 1
通过上述实例可以发现,假如了闭包实现之后,在student方法中通过添加返回提供方法的对象来实现对属性的访问权限的控制。在本例中,name属性可读可写,但无法通过对象名.属性名来修改,必须通过调用get/set方法才能操作该属性。而num属性则纯粹是私有变量,外界无法访问和修改。