一、关于闭包
1、闭包:一个拥有许多变量和绑定了这些变量的环境表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
2、闭包的特点:
1)、作为一个函数变量的一个引用,当函数返回时,其处于激活状态。
2)、一个闭包就是当一个函数返回时,一个人没有释放资源的栈区。
javascript允许使用内部函数——即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问他们所在的外部函数中声明的所有局部变量、
参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。
二、闭包的写法
js中一切皆为对象,函数也是对象的一种。
1、给函数添加一些属性
通过使用闭包,我们可以模拟面向对象的代码风格;更优雅,更简洁的表达出代码;在某些方面提升代码的效率
1、匿名函数自执行(有的函数只需要执行一次,其内部变量无需维护)
在js中声明变量时没有加var关键字,会默认添加到全局对象的属性上去,这样会容易造成,别的函数可能误用这些变量,造成全局对象过于庞大,影响访问速度(变量的取值需要从原型链上遍历的)。
2、结果缓存
我们需要做的是将计算结果的值储存起来,当调用这个函数的时候,首先在缓存中查找,如果没有,则进行计算,然后更新缓存并返回值,如果找到了,直接返回找到的值就可以。闭包正是可以做到这一点,因为他不会释放外部的引用,从而函数内部的值可以得以保留。
3、封装
1、闭包:一个拥有许多变量和绑定了这些变量的环境表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
2、闭包的特点:
1)、作为一个函数变量的一个引用,当函数返回时,其处于激活状态。
2)、一个闭包就是当一个函数返回时,一个人没有释放资源的栈区。
javascript允许使用内部函数——即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问他们所在的外部函数中声明的所有局部变量、
参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。
二、闭包的写法
js中一切皆为对象,函数也是对象的一种。
1、给函数添加一些属性
function Circle(r){
this.r = r;
}
Circle.PI = 3.14159;
Circle.prototype.area = function() {
return Circle.PI * this.r * this.r;
}
var c = new Circle(1.0);
alert(c.area());
2、声明一个变量,将一个函数当作值赋给变量。
var Circle = function() {
var obj = new Object();
obj.PI = 3.14159;
obj.area = function(r){
return this.PI * r * r;
}
return obj;
}
var c = new Circle();
alert(c.area(2.0));
3、new一个对象,然后给对象添加属性和方法
var Circle = new Object();
Circle.PI = 3.14159;
Circle.Area = function(r){
return this.PI * r * r;
}
alert(Circle.Area(2.0));
4、使用声明一个空对象,var obj = {}
var Circle = {
"PI":3.14159,
"area":function(r){
return this.PI * r * r;
}
};
alert(Circle.area(2));
5、直接声明函数
var Circle = new Function("this.PI = 3.14159;this.area = function(r){return r * r * this.PI;}");
alert((new Circle()).area(2));
三、闭包的用途
通过使用闭包,我们可以模拟面向对象的代码风格;更优雅,更简洁的表达出代码;在某些方面提升代码的效率
1、匿名函数自执行(有的函数只需要执行一次,其内部变量无需维护)
在js中声明变量时没有加var关键字,会默认添加到全局对象的属性上去,这样会容易造成,别的函数可能误用这些变量,造成全局对象过于庞大,影响访问速度(变量的取值需要从原型链上遍历的)。
var data = {
table:[],
tree:{}
};
(function(dm){
for(var i = 0;i < dm.table.rows;i++){
var row = dm.table.rows[i];
for(var j = 0;j < row.cells;i++){
drawCell(i,j);
}
}
})(data);
创建了一个匿名函数,并立即执行它,由于外部无法引用他内部的变量,因此在函数执行完后会立刻释放资源,关键不会污染全局对象。
2、结果缓存
我们需要做的是将计算结果的值储存起来,当调用这个函数的时候,首先在缓存中查找,如果没有,则进行计算,然后更新缓存并返回值,如果找到了,直接返回找到的值就可以。闭包正是可以做到这一点,因为他不会释放外部的引用,从而函数内部的值可以得以保留。
var CachedSearchBox = (function(){
var cache = {},
count = [];
return {
attachSearchBox:function(dsid){
if(dsid in cache){ //判断结果是否在缓存中
return cache[dsid]; //直接返回缓存中的对象
}
var fsb = new uikit.webctrl.SearchBox(dsid);//新建
cache[dsid] = fsb; //更新缓存
if(count.length > 100){ //保证缓存的大小<=100
delete cache[count.shift()];
}
return fsb;
},
clearSearchBox:function(dsid){
if(dsid in cache){
cache[dsid].clearSeleection();
}
}
};
})();
CachedSearchBox.attachSearchBox("input");
这样我们二次调用的时候,就会从缓存中取到该对象。
3、封装
var person = function(){
//变量作用域为函数内部,外部无法访问
var name = "default";
return {
getName:function(){
return name;
},
setName:function(newName){
name = newName;
}
}
}();
print(person.name);
print(person.getName());
person.setName("abruzzi");
print(person.getName());
4、实现类和继承
function Person(){
var name = "default";
return {
getName:function(){
return name;
},
setName:function(newName){
name = newName;
}
}
};
var p = new Person();
p.setName("Tom");
alert(p.getName());
var Jack = function(){};
//继承自Person
Jack.prototype = new Person();
//添加私有方法
Jack.prototype.Say = function(){
alert("Hello,my name is Jack");
};
var j = new Jack();
j.setName("Jack");
j.Say();
alert(j.getName());
在此我们定义了Person,他就像一个类,我们new一个Person对象,并访问它的方法。然后又定义了jack,继承Person,并添加自己的方法。