Javascript--闭包(closure)

203 阅读2分钟

闭包 closure

1.变量的作用域

变量的作用域为全局变量和局部变量
Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量
 var n=999;

  function f1(){
    alert(n);
  }

  f1();   // 999
在函数外部自然无法读取函数内的局部变量
function f1(){
    var n=999;
  }

  alert(n); // error  报错
在函数内部声明,必须用var 声明
	var n=999;//全局变量,任何函数都可以访问
			function demo(){
				console.log(n);
				
			}
			demo()
			function func(){//在函数内部声明,必须用var 声明
				var num=888;//局部变量,只有在函数内部可以访问,私有
				
			}
			console.log(num);

2.如何从外部读取局部变量?

在函数的内部,再定义一个函数。
 function f1(){

    var n=999;

    function f2(){
      alert(n);
    }

    return f2;

  }

  var result=f1();

  result(); // 999

3.变量提升

                            function demo(){
                            //在函数内部声明变量的时候,如果未回 var 关键字,则函数运行后,该变量提升为全局变量
				n="work hard at javascript";
			}
                               demo()
                               console.log(n);
                               var name="I decide to"
                               var total=name+n;
                               console.log(total);
			

4.闭包概念

将函数局部变量变成全局变量,连接函数内部和外部

5.闭包应用

                                function f1() {
				var n = 999;
				add = function() {
					alert(n += 1);
				}
				function f2() {
					alert(n);
				}
				return f2;
			}
			var result = f1();
			result();//999
			add();//1000
			result();//1000

6.闭包思考题

1.The Window
var name ="The Window";
			var object ={
				name:"my object",
				getNameFunc: function(){
					return function(){
						return this.name
					};
				}
				
			};
			alert(object.getNameFunc()());   //The Window
2.my object
var name ="The Window";
			var object ={
				name:"my object",
				getNameFunc: function(){
					var that =this //用来改变this 指向
					return function(){
						return that.name
					};
				}
				
			};
			alert(object.getNameFunc()());//my object

7.闭包演示

结构:
<style type="text/css">
			p {
				background: lightblue;
			}
		</style>
	</head>
	<body onclick="init()">
		<p>产品 0</p>
		<p>产品 1</p>
		<p>产品 2</p>
		<p>产品 3</p>
		<p>产品 4</p>
	</body>
(1).
                function init() {
				var pAry = document.getElementsByTagName("p");
				for (var i = 0; i < pAry.length; i++) {
					pAry[i].onclick = function() {
						alert(i);
					}
				}
			}
(2).
                            function init() {
				var pAry = document.getElementsByTagName("p");
				
				for (var i = 0; i < pAry.length; i++) {
					pAry[i].index=i;   //pAry[i]  对象
					pAry[i].onclick = function() {
						alert(this.index);
					}
				}
			}
(3).
                            function init() {
				var pAry = document.getElementsByTagName("p");
				
				for (var i = 0; i < pAry.length; i++) {
					
					(pAry[i].onclick = function() {
						alert(arguments.callee.i);
					}).i=i;
				}
			}
(4).
                            function init() {
				var pAry = document.getElementsByTagName("p");
				for (let i = 0; i < pAry.length; i++) {
					pAry[i].onclick = function() {
						alert(i);
					}
				}
			}
(5).
                            function init() {
				var pAry = document.getElementsByTagName("p");
				for (var i = 0; i < pAry.length; i++) {
					(function() {
						var temp = i;  
						pAry[i].onclick = function(){
							alert(temp);
						}
					})(); //iife立即执行函数
				}
			}

8.闭包注意事项

1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。
解决方法是:
在退出函数之前,将不使用的局部变量全部删除。
2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。