渡一教育公开课web前端开发JavaScript精英课学习笔记(六)函数及作用域

函数作用域

函数有个隐藏的属性[[scope]],这个属性就是作用域,其存储了运行期上下文的集合。

[[scope]]存储运行期上下文集合,这些集合呈链式关系,就是作用域链。

[[scope]]属性结构

第一个元素 >>> 当前运行函数的 ActivationObject

第二个元素 >>> 当前运行函数父函数的 ActivationObject

第三个元素 >>> 当前运行函数父函数的父函数的 ActivationObject

…………

最后元素 >>>  GlobalObject

<script type = "text/javascript">
	function a(){
		function b(){
			function c(){
				function d(){
				}
				d();
			}
			c();
		}
		b();
	}
	function e(){
	}
	// a 和 e 函数定义时它们的 [[scope]] 属性中只有一个元素,就是 GlobalObject(全局运行时上下文)
	//当要执行 a 函数时,a 函数就创建自己的 ActivatonObject(运行时上下文),存储在属性[[scope]]中,并放置到顶端(第1个元素)
	//这时 a 函数的[[scope]]属性的内容是
	//第一个元素   ActivationObject(a的运行时上下文)
	//第二个元素   GlobalObject(全局的运行时上下文)
	a();
	//当执行 a 函数时,b 函数运行前,b函数属性[[scope]]引用了函数 a 的[[scope]]属性,并且b函数创建自己的 ActivationObject。
	//这时 b 函数的[[scope]]属性的内容是
	//第一个元素   ActivationObject(b的运行时上下文)
	//第二个元素   ActivationObject(a的运行时上下文)
	//第三个元素   GlobalObject(全局的运行时上下文)
	//当 b 函数执行时,查找变量的顺序是[[scope]]属性,从上往下查找。直到找到第一个符合的停止。
	//当 b 函数执行完后,销毁自己创建ActivationObject
	//这时 b 函数的[[scope]]属性的内容变为
	//第一个元素   ActivationObject(a的运行时上下文)
	//第二个元素   GlobalObject(全局的运行时上下文)
	//当执行 b 函数时,c 函数运行前,c函数属性[[scope]]引用函数 b 的[[scope]]属性,并且c函数创建自己的 ActivationObject。
	//以此类推,直到所有函数执行完毕。
</script>

闭包:

内部函数被返回到外部时,内部函数本身存着父函数的ActivationObject,即使父函数执行完,取消了对 ActivationObject引用,但内部函数依然可以存取父函数变量。这样就产生闭包。闭包会导致原有作用域链不释放,造成内存泄漏。

闭包的作用:实现公有变量(累加器)、缓存(存储结构)、实现封装,属性私有化、模块化开发,防止污染全局变量。

<script type = "text/javascript">
	function a(){
		var num = 0;
		function b(){
			num ++;
			document.write("num = ",num,"<br/>")
		}
		return b;
	}
	var demo = a();
	demo();//1
	demo();//2
	demo();//3
</script>

闭包应用:缓存

<script type = "text/javascript">
	function eater(){
		var food = [];
		var obj = {
			eat:function(){
				if(food.length < 1){
					document.write("There is no food!<br/>");
				}
				else{
					document.write("i am eating " + food[food.length - 1],"<br/>");
					food.pop();
				}
			},
			push:function(myFood){
				food.push(myFood);
			}
		}
		return obj;
	}
	var eater1 = eater();
	eater1.push("apple");
	eater1.push("banana");
	eater1.eat();
	eater1.push("orange");
	eater1.eat();
	eater1.push("cake");
	eater1.eat();
	eater1.eat();
	eater1.push("banana");
	eater1.eat();
	eater1.eat();
</script>

立即执行函数(初始化功能的函数)

应用在只执行一次的函数。只有函数表达式才能被执行符号()执行,函数声明不能被执行。

<script type = "text/javascript">
	(function(){document.write("ohohoh!!","<br/>")}());//W3C推荐立即执行函数格式
	(function(){document.write("ohohoh!!","<br/>")})();
	var x =(function(a,b,c){
          return a + b + c;
			}(1,2,3))
	document.write(x,"<br/>");
	var y = function demo(){
		document.write("hahaha!!!","<br/>")
	}();
	//function error(){document.write("ohohoh!!","<br/>");}();函数声明不能被执行
	+function error(){document.write("ohohoh!!","<br/>");}(); 
</script>

立即执行函数与闭包应用

<script type = "text/javascript">
	//立即执行函数,闭包保存循环变量 ii 的使用方式。
	function test(){
		var arr = [];
		for (var i = 0; i < 10; i++) {
			(function(ii){
				arr[ii] = function(){
				document.write("i = " + i + " ii = " + ii + "<br/>")
			}	
			}(i))
		}
		return arr;
	}
	var myArr = test();
	for(var j = 0;j < myArr.length;j++){
		myArr[j]();
	}
</script>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值