闭包,this指向,内存泄漏
通过自我执行来执行匿名函数
(function(){ //(匿名函数)(); 第一圆括号放匿名函数,是一个表达式,第二圆括号执行
return 'Lee';
})();
//把匿名函数自我执行的返回值赋值给变量
var box=(function(){
return 'Lee';
})();
alert(box);
//自我执行匿名函数的传参
(function(age){
alert(age);
})();
//闭包,函数里面放一个匿名函数
function box(){
return function(){ //闭包
return 'Lee';
}
}
alert(box()());
//通过闭包返回局部变量
function box(){
var user='Lee';
return function(){ //通过匿名函数返回box()局部变量
return user;
};
}
alert(box()());
//使用匿名函数实现局部变量驻留内存中从而累加
function box(){
var age=100;
return function(){
age++;
return age;
}
}
var b=box();
alert(b());
alert(b());
alert(b());
alert(b());
b=null; //解除引用,等待垃圾回收
//循环里匿名函数取值问题
function box(){
var arr=[];
for(var i=0;i<5;i++){
arr[i]=function(){
return i;
}
}
return arr;
}
var b=box();
for(var i=0;i<b.length;i++){
alert(b[i]()); //[5,5,5,5,5]
}
//改1
function box(){
var arr=[];
for(var i=0;i<5;i++){
arr[i]=(function(num){ //通过自我及时执行匿名函数
return num;
})(i);
}
return arr;
}
var b=box();
for(var i=0;i<b.length;i++){
alert(b[i]()); //[0,1,2,3,4]
}
//改2 这种方法用的更多
function box(){
var arr=[];
for(var i=0;i<5;i++){
arr[i]=(function(num){
return function(){ //因为闭包可以将变量驻留在内存中
return num;
}
})(i);
}
return arr;
}
var b=box();
for(var i=0;i<b.length;i++){
alert(b[i]());
}
//关于this对象
var box={
getThis:function(){
return this;
}
}
alert(box.getThis()); //[object Object]
var box={
getThis:function(){
return function(){ //闭包在运行时指向window,因为闭包并不属于这个对象的属性或方法。
return this;
}
}
}
alert(box.getThis()()); //[object Window]
var box={
user:'The Box',
getUser:function(){
return function(){
return this.user;
}
}
}
alert(box.getUser().call(box)); //对象冒充,就可以指向box,打印出The Box
下面是重点:
var box='The Window';
var box={
user:'The Box',
getUser:function(){
//这里作用域的this是Box
var that=this;
return function(){
//这里作用域的this是window
return that.user;
}
}
};
alert(box.getUser()()); //打印出The Box
----------------------------------------------------------------------
内存泄漏:闭包需要手动解除引用 b=null;
function box(){
var oDiv=document.getElementById('oDiv');
var test=oDiv.innerHTML;
oDiv.onclick=function(){
alert(test);
};
oDiv=null; //解除引用,等待垃圾回收
}
box();
----------------------------------------------------------------------
封装的好处:安全性,数据保护,封装细节,程序可控性
function box(){
for(var i=0;i<5;i++){ //块级作用域(虽然js并没有这个概念)
}
alert(i); //出了for循环,还能访问到i
}
box();
//使用块级作用域(私有作用域)
function box(){
(function(){
for(var i=0;i<5;i++){
alert(i);
}
})(); //出了这个私有作用域,变量立即被销毁
alert(i); //这里就不认识了
}
box();
//私有变量
function box(){
var age=100; //私有变量
}
box();
function Box(){
this.age=100; //属性,公有的
this.run=function(){ //方法,公有的
return '运行中...'
};
}
var box=new Box();
alert(box.age);
alert(box.run());
function Box(){
var age=100; //私有变量
function run(){ //私有函数
return '运行中...';
}
}
var box=new Box();
alert(box.run()); //出错
function Box(){
var age=100; //私有变量
function run(){ //私有函数
return '运行中...';
}
this.publicGo=function(){ //对外可见的公共接口,特权方法
return age+run();
};
}
var box=new Box();
alert(box.publicGo());
//通过构造函数传参
function Box(value){
var user=value; //私有变量
this.getUser=function(){
return user;
}
}
var box=new Box('Lee');
alert(box.getUser()); //但是对象的方法,在多次调用的时候,会创建多次,可以使用静态私有变量来避免这个问题
。
var box2=new Box('kkk');
alert(box.getUser()); //但是对象的方法,在多次调用的时候,会创建多次,可以使用静态私有变量来避免这个问题
。
可以使用下面的方法(重点):
function Box(value){
var user=value; //私有变量
this.getUser=function(){
return user;
};
this.setUser=function(value){
user=value;
}
}
var box=new Box('Lee');
alert(box.getUser());
box.setUser('OOO');
alert(box.getUser());
------------------------------------------------
静态私有变量: 共享
(function(){
var user=''; //私有变量
function Box(){} //构造函数,但在函数里写构造方法,不支持
})();
var box=new Box(); //出错 Box is not defined
(function(){
var user=''; //私有变量
Box=function(value){ //全局构造函数
user=value;
};
Box.prototype.getUser=function(){
return user;
}
})();
var box=new Box('Lee');
alert(box.getUser());
var box2=new Box('kkk');
alert(box.getUser());
//使用了prototype导致方法共享了,而user也就变成静态属性了。(所谓静态属性,即共享于不同对象中的属性。)
------------------------------------------------------------------------------------------------
//什么叫单例,就是永远只实例化一次,其实就是字面量对象声明方式
var box={
user:'Lee';
run:function(){
return '运行中...';
}
}
var box=function(){
var user='Lee'; //私有变量
function run(){ //私有函数
return '运行中...';
}
return {
publicGo:function(){ //对外公共接口的特权方法
return user+run();
}
}
}();
alert(box.publicGo());
上面方法也可以这样写:
var box=function(){
var user='Lee'; //私有变量
function run(){ //私有函数
return '运行中...';
}
var obj={
publicGo:function(){ //对外公共接口的特权方法
return user+run();
}
};
return obj;
}();
alert(box.publicGo());
增强型的:
function Desk(){}
var box=function(){
var user='Lee';
function run(){
return '运行中...';
}
var desk=new Desk();
desk.publicGo=function(){
return user+run();
}
return desk;
}();
alert(box.publicGo());