简单的块级作用域:
javascript没有块级作用域的概念
function test(){ for(var i = 1 ; i <=5; i++){ //i alert(i); } alert(i); //6 } test();最后会输出6. 只有当test执行完毕后I才会被垃圾收回机制收回。
为了避免这种情况发生,可以把里面的for循环作为一个单独的域。使用function包含起来。
function test(){ function(){ for(var i = 1 ; i <=5; i++){ //i alert(i); } }; alert(i); }
但是function不会自己执行,在js中()表示执行
function test(){ (function(){ for(var i = 1 ; i <=5; i++){ //i alert(i); } })(); alert(i); } test();这样就不会把6输出。
把一个函数直接使用(function(){...})()形式可以直接执行。
(function(){alert('我直接执行了!');})();
闭包
在程序语言中,所谓闭包,是指语法域位于某个特定的区域,具有持续参照(读写)位于该区域内自身范围之外的执行域上的非持久型变量值能力的段落。这些外部执行域的非持久型变量神奇地保留他们在闭包最初定义(或创建)时的值 。
上面的解释不用完全理解(我刚刚看到也懵了),下面直接看代码:
var name = "xiao A"; var obj = { name : "xiao B" , getName: function(){ return function(){ return this.name; } } }; alert(obj.getName()());结果不是输出“xiao B”,而是“xiao A”
原因: 当我们alert(obj.getName());时,返回结果为:
function(){ return this.name; }
这个时候使用obj.getName()(),作用于已经是在window中了,在obj的外层。返回“xiao A”相当于如下代码:
var name = "xiao A"; var obj = { name : "xiao B" , getName: function(){ return function(){ return this.name; } } }; alert(obj.getName()()); var k = obj.getName(); //全局作用域 //alert(typeof k); // function类型 alert(k());结果一样输出“xiao A”
如果想要输出“xiao B”,需要一个变量保存当前的调用者的对象。
var name = "xiao A"; var obj = { name : "xiao B" , getName: function(){ // this总是指向调用者 var o = this; return function(){ return o.name; } } }; //alert(obj.getName()()); var k = obj.getName(); alert(k());用o保存obj的this对象,总是指向调用者,getName()的调用者是obj,所以o就代表obj,返回的就是o.name
闭包说简单些:闭包:一个函数 可以访问另外一个函数作用域中的变量
闭包示例:
function f(x){ // 假设为 2级作用域 var temp = x ; //局部变量 //temp已经没有被使用 return function(x){ // 3级作用域 (function 有了一个执行域 var obj) temp += x ; // 又被使用了 alert(temp); } } var a = f(50); //alert(a); a(5); a(10); a(20);当我调用f(50)的时候temp=50,返回function(x){temp+=x;alert(temp);}并赋给a。然后再执行a(5),输出55。再执行a(10),输出65。再执行a(20),输出85。
当我return赋值给a后作用域和f(x)的作用域是一样的,按照一般说法就不能访问f里面的temp变量,temp变量会被垃圾回收机制收回,但不是这样,当垃圾回收机制检测到temp使用过后会继续检查return的函数,发现函数里面继续使用temp,会再次标记temp被使用。
当调用a(5)时候,检测到后面还调用a函数,用到temp变量,所以temp变量会再次被标记不会被回收。
简单的理解就是:这样我们就相当于在一个a函数中访问f函数中的temp变量。