1,函数作为返回值
var a=20 function haha() { console.log('haha1') } function wo() { // var a=10 function haha() { console.log('haha2') } return function () { //匿名函数是在wo函数里面声明的,就先在wo函数里面找需要的变量 console.log(a) haha() } } var fn=wo() fn() //虽然在全局环境调用了返回的匿名函数,但是匿名函数会去往声明它的环境里面向上寻找
2,函数作为参数时
var a=20 function wo(fn) { var a=10 fn() //ni函数虽然是在wo函数里面被调用,但是ni函数是在全局环境中被声明的,所以先去全局环境找 } function ni() { console.log(a) } wo(ni)
————————-先看以上案例—————————-
首先简单看一下一个简单的闭包
function box(){
alert(‘匿名函数外’);
return function(){ return ‘fff’; };
};
调用方法一:alert(box()());
调用方法二:
var b=box();//当我们把box函数赋值给了变量b时,就已经执行了函数box,但是没执行到匿名函数而已。
alert(b()); //这一步其实就只调用了function(){ return ‘fff’; };
一个函数里面有匿名函数。
2,闭包的作用就是避免声明一个全局变量,消耗资源或者出现重复重命名导致不可预测结果,其实效果就是
一个:不声明全局变量的情况下,拥有和全局变量一样的效果,而且暂时住宅内存,不用的时候可以释放出去,
这样就可以节省资源。
一个简单例子来说明闭包的作用。
var age=100; //全局变量age function box(){ age++; //累加全局变量 return age; }; alert(box()); alert(box()); alert(box());
全局变量好用但是我们做项目的时候能避免使用全局就尽量避免
闭包例子:
function box(){ var age=100; //外部直接是不能方面的 alert('var age被执行了一次而已'); return function(){ age++; alert('匿名函数不断的被执行'); return age; } } alert(box()()); alert(box()()); alert(box()()); //这样调用是不能实现累加的,因为这样调用也不断的执行到了var age=100;age也就不断的被初始化了。 我们要这样调用: var b = box();//执行到了var age=100; 也就是在box函数中内部中声明了age=100,但是没执行匿名函数。 alert(b()); //第一次调用时,执行了box函数里面的全部代码。 alert(b()); //第二次调用时,其实就只执行了匿名函数那部分而已,没有跳出box函数外。 alert(b()); //没跳出box函数,就只执行了匿名函数部分。 b=null; //这样就注销了age在内存里的住宅。
————————————-
闭包的 数组循环取值问题的应用注意事项
//方法1
function box(){
var wo=[];
for(var i=0;i<5;i++){
wo[i]=(function(mun){ return mun; })(i);
}
return wo;
}
alert( box()[0] );
alert( box()[1] );
//方法2
function box(){
var wo=[];
for(var i=0;i<5;i++){
wo[i]=(function(mun){
return function(){
return mun;
}
})(i);
}
return wo;
}
alert( box()[0]() );
alert( box()[1]() );
闭包中的this指向问题。
var box={
run:function(){
return function(){
return this; //这个this只得是window
}
}
}
*闭包其实模拟了全局的环境闭包里面的变量只所以可以暂时住宅就是因为闭包环境模拟了全局,所以闭包里面的this才能指向window
那么如何将闭包里面的this指向作用域的对象呢?
方法一:对象冒充
box.run().call(box) //让闭包冒充box
方法二:
var box={
run:function(){
var that=this; //把box的this赋值给一个变量
return function(){
return that; //在闭包中使用box的this变量
}
}
}
私有作用域,举两个例子。
例子一:
function box(){
for(var i=0;i<5;i++){ //在JS中for定义的i在循环体里利用完了,i在循环体外仍然可以用。
alert(i);
}
alert(i); //这里的i是循环体中的i,在循环体外面还可以用。
}
box();
我们不想让循环体里面的i在外面也有效可以这么做:
function box(){
(function(){
for(var i=0;i<5;i++){
alert(i);
}
})(); //跳出自调用循环体的i已经被注销了
alert(i); //这里的i和循环体的i没有关系
}
例子二:
在项目中都是很多程序员做的,不可能每个人都声明变量在全局中,这样也许会有人命名重复的,同时
命名多了也占资源,所以我们需要自调用函数的方法冒充声明全局变量,函数执行完跳出之后,变量也
会自动销毁。
;(function(){
var age=100; //这里声明的全局变量暂时存在内存中。
})();
//到了函数外面age跟已经不存在了。
alert(age); //这里的age跟自调用函数里面的age没关系。
所以在项目开发中,私有作用域的作用很重要。
私有变量
var box=function(value){
var wo=value; //外部直接是无法调用的
this.run=function(){ //只能在内部提供接口,外部才能访问
return wo;
}
}
var p1=new box(‘陈’);
alert(p1.run());
在私有作用域中达到构造函数方法共享
我们平时平时都是这样写
var box=function(value){
var wo=value;
box.prototype.run=function(){
return wo;
}
}
var p1=new box(‘陈’);
alert(p1.run());
var p2=new box(‘fff’); //p2覆盖了修改了原型函数value值
alert(p1.run()); //即使是弹出了p1.run()也能得到p2修改的值。
以上是我们平时的写法。
如果要在私用的作用域情况下创建实现以上效果我们要这样做:
我们可以使用静态私有变量也能达到以上效果
(function(){
var wo=”; //私用
box=function(value){ //不加var创建全局构造函数,这样外面才可以实例化此构造函数
wo=value;
}
box.prototype.run=function(){
return wo;
}
box.prototype.setrun=function(value){
return wo=value;
}
})();
var p1 = new box(‘我’);
alert(p1.run());
var p2 = new box(‘你’);
alert(p1.run());
var p3 = new box();
alert(p1.setrun(‘他’));