js的闭包--js详解(十五)

1、函数的执行顺序

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<title>js01_hello</title>
	<meta name="author" content="Administrator" />
	<script type="text/javascript">
	fn1();
	//不会报错,对于通过function fn()这种写法来定义的函数,永远都会被最先初始化
	function fn1() {
		alert("fn1");
	}
	
	fn2();
	//使用如下方式定义函数,不会被先执行,如果在之前调用该函数就会报错
	/**
	 * 以下函数的定义方式是现在内存中创建了一块区域,之后通过一个fn2的变量
	 * 指向这块区域,这块区域的函数开始是没有名称的 ,这种函数就叫做匿名函数(也就是闭包)
	 */
	var fn2 = function() {
		alert("fn2");
	}	
	</script>
</head>
<body>
</body>
</html>

2、作用域链

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<title>js01_hello</title>
	<meta name="author" content="Administrator" />
	<script type="text/javascript">
	/**
	 * 在js中当进行函数的调用,会为每一个函数增加一个属性SCOPE,通过这个属性来指向一块内存
	 * 这块内存中包含有所有的上下文使用的变量,当在某个函数中调用了新函数之后,新函数依然
	 * 会有一个作用域来执行原有的函数的SCOPE和自己新增加的SCOPE,这样就形成一个链式结构
	 * 这就是js中的作用域链
	 */
	var color = "red";
	
	var showColor = function() {
		alert(this.color);
	}
	
	function changeColor() {
		var anotherColor = "blue";
		function swapColor() {
			var tempColor = anotherColor;
			anotherColor = color;
			color = tempColor;
		}
		swapColor();
	}
	
	changeColor();
	
	showColor();
	</script>
</head>
<body>
</body>
</html>

以下是内存模型分析图

3、比较方法的例子

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<title>js01_hello</title>
	<meta name="author" content="Administrator" />
	<script type="text/javascript">
	/**
	 * 通过以下操作带来最大的好处是,compareObjectFunction的作用域变大了
	 * 当compareObjectFunction结束之后,prop这个变量依然存在
	 */
	function compareObjectFunction(prop) {
		//匿名函数
		return function(obj1,obj2) {
			if(obj1[prop]>obj2[prop]) return 1;
			else if(obj1[prop]<obj2[prop]) return -1;
			else return 0;
		}
	}
	var o1 = {name:"Leon",age:23};
	var o2 = {name:"Ada",age:28};
	//此时就是基于name来进行比较
	/*
	 * 在java或者c++中,以下代码执行完成之后,需要进行内存的释放
	 * 此时对于java和c++这些静态语言而言,prop会被释放
	 * 但是在js中,这个作用域却被放大了
	 */
	var compare = compareObjectFunction("age");
	//此时就比较了o1和o2
	/*
	 * 在js中,prop在这里依然可以被访问,这种通过返回函数来扩大函数的作用域的方法
	 * 就是闭包
	 */
	var rel = compare(o1,o2);
	alert(rel);
	</script>
</head>
<body>
</body>
</html>

4、闭包中的var变量

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<title>js01_hello</title>
	<meta name="author" content="Administrator" />
	<script type="text/javascript">
	function fn1() {
		//创建了一个数组
		var fns = new Array();
		//i这个变量是保存在fn1这个作用域中的
		for(var i=0;i<10;i++) {
			//数组中方的值是一组函数
			fns[i] = function() {return i;}
		}
		return fns;
	}
	
	var fs = fn1();
	for(var i=0;i<fs.length;i++) {
		//此时通过闭包来调用所有函数,当输出i的时候,首先在自己的作用域查找(没有找到),没有则会去上一级的作用域中查找
		//这个时候i的值已经10,所以连续输出了10个10
		document.write(fs[i]()+"<br/>");
	}
	</script>
</head>
<body>
</body>
</html>

 5、解决4中闭包var问题

  

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<title>js01_hello</title>
	<meta name="author" content="Administrator" />
	<script type="text/javascript">
	function fn1() {
		//创建了一个数组
		var fns = new Array();
		//i这个变量是保存在fn1这个作用域中的
		for(var i=0;i<10;i++) {
			//num这个变量是保存在fns这个tf这个作用域,每一个闭包的num都是不一样
			//所以此时所消耗的内存特别的大
			var tf = function(num) {
				fns[num] = function() {
					return num;
				}
			}
			tf(i);
		}
		return fns;
	}
	
	var fs = fn1();
	for(var i=0;i<fs.length;i++) {
		//每一个fs都是在不同作用域链中,num也是保存在不同的作用域中,所以输出0-9
		document.write(fs[i]()+"<br/>");
	}
	</script>
</head>
<body>
</body>
</html>

 6、闭包中的this

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<title>js01_hello</title>
	<meta name="author" content="Administrator" />
	<script type="text/javascript">
	var name = "window";
	var person = {
		name:"zhangsan",
		age:23,
		say:function() {
			alert(this.name);	//zhangsan
			return function() {
				return this.name;	//window
			}
		}
	}
	/*
	 * 当完成person.say()之后,这个函数就调用结束了,在这个函数调用结束之前
	 * this是指向person,但是在调用匿名函数的时候,this就指向window,所以
	 * 得到的结果是window
	 * 
	 */
	alert(person.say()());
	</script>
</head>
<body>
</body>
</html>

 7、解决6中闭包this问题

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<title>js01_hello</title>
	<meta name="author" content="Administrator" />
	<script type="text/javascript">
	var name = "window";
	var person = {
		name:"zhangsan",
		age:23,
		say:function() {
			//that就指向person
			var that = this;
			return function() {
				return that.name;
			}
		}
	}
	/*
	 * 此时that是指向person的,所以调用that.name就是person中name
	 * 
	 */
	alert(person.say()());
	</script>
</head>
<body>
</body>
</html>

 8、js的块作用域

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<title>js01_hello</title>
	<meta name="author" content="Administrator" />
	<script type="text/javascript">
	for(var i=0;i<10;i++) {
		
	}
	//在js中没有块作用域,不管是使用循环还是判断之后,这个变量会一直存在
	/*
	 * 所以当在全局使用某个变量进行循环或者判断之后,这个变量可能会影响
	 * 到函数中的变量,所以在特殊情况不要使用全局变量,而且使用全局变量
	 * 在作用域链的最上层,访问是最慢的
	 */
	var i;//此时会认为是无效语句,除非使用var i = 0;
	alert(i);	//10
	</script>
</head>
<body>
</body>
</html>

 9、使用闭包解决块作用域问题

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<title>js01_hello</title>
	<meta name="author" content="Administrator" />
	<script type="text/javascript">
	/*
	 * 在一个团队进行开发时,可能会涉及到定义同名的全局变量,所以在开发中
	 * 一定养成如下习惯,将全局变量的代码放到一个匿名函数,并且马上调用
	 * 匿名函数,这样也可以执行全局变量的代码,但是这些变量就被控制在开发
	 * 人员想要控制的作用域中了
	 */
	//在function的{}后不能直接调用,一定要加上括号
	// function(){
		// for(var i=0;i<10;i++) {
// 		
		// }	
	// }();
	(function(){
		for(var i=0;i<10;i++) {
		
		}	
	})();
	
	function fn() {
		alert(i);
	}
	fn();
	</script>
</head>
<body>
</body>
</html>

 10、js中的私有变量

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<title>js01_hello</title>
	<meta name="author" content="Administrator" />
	<script type="text/javascript">
	function Person(name) {
		/**
		 * 此时就没有办法直接访问name这个属性,因为没有this.name
		 * 要访问name只能通过this.getName,this.setName
		 * 但是使用这种方式创建私有变量带来的问题是,每个对象都存储大量的函数
		 * 解决的办法是通过静态私有变量来解决
		 */
		this.setName = function(value) {
			name = value;
		}
		this.getName = function() {
			return name;
		}
	}
	
	var p = new Person("aa");
	alert(p.getName());
	p.setName("bb");
	alert(p.getName());
	</script>
</head>
<body>
</body>
</html>

 11、通过闭包实现静态私有变量

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<title>js01_hello</title>
	<meta name="author" content="Administrator" />
	<script type="text/javascript">
	var Person;
	(function(){
		//name正在函数结束之后就消失,在外面是无法引用的
		var name = "";
		Person = function(value){
			name = value;
		}
		Person.prototype.setName = function(value) {
			name = value;
		}
		Person.prototype.getName = function() {
			return name;
		}
	})();
	
	var p1 = new Person("aa");
	alert(p1.getName());
	p1.setName("bb");
	alert(p1.getName());
	</script>
</head>
<body>
</body>
</html>

js基本上讲完了,可能有些地方写的不是很清楚,因为也是看视频而写的博客记录,不是原创

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值