文档章节

javascript之块级作用域的概念和闭包

指尖残雪
 指尖残雪
发布于 2016/05/22 23:57
字数 848
阅读 13
收藏 0

简单的块级作用域:

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变量。






本文转载自:http://blog.csdn.net/bq1073100909/article/details/48706145

指尖残雪
粉丝 7
博文 73
码字总数 0
作品 0
上海
后端工程师
私信 提问
原生javascript学习:javascript闭包实例

之前看zakas的Professional JavaScript,读过闭包的章节,当时觉得理论上是理解了,把书上的案例都实践了一遍。但例子是纯粹控制台调试实现的,印象不深刻,今天练习原生javascript的时候碰上...

黎宇浩
2012/06/15
319
0
浅谈var、let、闭包以及立即执行函数(namespace)

首先我们来看个常见的例子 上述答案有同学可能回答 6和12345,那么就大错特错了 分析:上述例子其实是一样的 不管有没有存在异步函数(这里的setTimeout就是异步函数),例子一我执行a6和例子...

vnues
06/25
0
0
你不知道的JavaScript·第一部分

第一章: 作用域是什么 1、 编译原理 JavaScript 被列为 ‘动态’ 或 ‘解释执行’ 语言,于其他传统语言(如 java)不同的是,JavaScript是边编译边执行的。 一段源码在执行前会经历三个步骤...

曾田生z
2018/06/25
0
0
好程序员Web前端培训入门之JS基础知识梳理汇总

好程序员Web前端入门之JS基础知识梳理汇总,Web前端工程师是当前各大企业都比较稀缺的人才,薪资待遇和就业前景都很不错。不论是专业还是非专业,有基础亦或是无基础,都想通过学习Web前端实...

好程序员IT
03/27
12
0
从 JS 编译原理到作用域(链)及闭包

虽然作用域相关知识是 JavaScript 的基础, 但要彻底理解必须要从原理入手. 从面试角度来讲, 词法/动态作用域、作用域(链)、变量/函数提升、闭包、垃圾回收 实属一类题目, 打通这几个概念并熟...

YanceyOfficial
04/08
0
0

没有更多内容

加载失败,请刷新页面

加载更多

golang微服务框架go-micro 入门笔记2.1 micro工具之micro api

micro api micro 功能非常强大,本文将详细阐述micro api 命令行的功能 重要的事情说3次 本文全部代码https://idea.techidea8.com/open/idea.shtml?id=6 本文全部代码https://idea.techidea8....

非正式解决方案
今天
4
0
Spring Context 你真的懂了吗

今天介绍一下大家常见的一个单词 context 应该怎么去理解,正确的理解它有助于我们学习 spring 以及计算机系统中的其他知识。 1. context 是什么 我们经常在编程中见到 context 这个单词,当...

Java知其所以然
昨天
3
0
Spring Boot + Mybatis-Plus 集成与使用(二)

前言: 本章节介绍MyBatis-Puls的CRUD使用。在开始之前,先简单讲解下上章节关于Spring Boot是如何自动配置MyBatis-Plus。 一、自动配置 当Spring Boot应用从主方法main()启动后,首先加载S...

伴学编程
昨天
7
0
用最通俗的方法讲spring [一] ──── AOP

@[TOC](用最通俗的方法讲spring [一] ──── AOP) 写这个系列的目的(可以跳过不看) 自己写这个系列的目的,是因为自己是个比较笨的人,我曾一度怀疑自己的智商不适合干编程这个行业.因为在我...

小贼贼子
昨天
7
0
Flutter系列之在 macOS 上安装和配置 Flutter 开发环境

本文为Flutter开发环境在macOS下安装全过程: 一、系统配置要求 想要安装并运行 Flutter,你的开发环境需要最低满足以下要求: 操作系统:macOS(64位) 磁盘空间:700 MB(不包含 IDE 或其余...

過愙
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部