zoukankan      html  css  js  c++  java
  • 讲解JavaScript中对闭包的理解

    1、JS中变量的作用域

    • 在理解闭包之前,我们得弄清楚JS中变量的作用域原理,它分为全局作用域和局部作用域,它有一个特点就是局部可以获取全局的声明变量,而全局却不能得到局部声明的变量,我们先来看一个小例子:
    		var num = 99;
    		function foo(){
    			var hit = 88;
    			console.log(num);
    		}
    		foo();   //99
    		console.log(hit);  //报错,找不到hit变量
    

    当然在局部声明变量的时候一定要用var或者let,不然会在全局生成一个变量,容易照成全局污染,上面代码如果hit没有var声明:

    		var num = 99;
    		function foo(){
    			hit = 88;
    			console.log(num);
    		}
    		foo();   //99
    		console.log(hit);  //88
    

    2、什么是闭包

    那么现在问题来了,如果我们非要从外部来读取局部变量中的声明变量呢,寻常方式不行,我们可以变通一下,就是在函数内部再嵌套一个函数,然后返回这个嵌套函数:

    		function foo(){
    			var hit = 88;
    			return function num(){
    				console.log(hit)
    			}
    		}
    		var num1 = foo();
    		num1();  //88
    

    这样,控制台就会打印出hit变量的值了,其实在上面的代码中,被返回的函数num()就产生了闭包,由于在js中,只有函数内部的子函数才能读取局部变量,所以可以把闭包理解成定义在一个函数内部的函数,简单的说,JavaScript允许使用内部函数:即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。

    3、闭包的用途

    • 相信大家对闭包的概念已经有了简单的认识,我们接着探讨闭包的表达形式以及用途。
      (1)匿名自执行函数
    		(function(){
    		  var foo = function(){
    		     console.log('执行完函数后销毁')
    		  };
    		  foo();
    		})();
    

    上面代码也是闭包的应用,运用于函数只会执行一次的场景,执行完便会被释放。
    (2)给对象设置私有变量

    		var result = function(){
    			var count = 1;
    			  
    			return function (){
    				count++;
    			    console.log(count)
    			  }
    		}()
    
    		result(); //2
    		result(); //3
    		result(); //4
    		result(); //5
    

    上面代码可以保存自己的私有变量,防止代码之间的冲突。
    (3)异步执行函数
    下面先看一个小例子:

    	for(var i=0;i<5;i++){
    				console.log(i);  //0,1,2,3,4
    	}
    	for(var i=0;i<5;i++){
    			setTimeout(()=>{
    				console.log(i); //5,5,5,5,5
    		},0)
    	}
    

    为什么会出现上述差异呢,原因在于setTimeout是异步加载,所以为先循环结束后输出最后结果,如果我们就是想实现输出0,1,2,3,4呢。那就要用到闭包了:

    	for(var i=0;i<5;i++){
    
    		(function(i){
    			setTimeout(()=>{
    				console.log(i); //0,1,2,3,4
    			},0);
    		})(i);
    	}
    

    上面就是异步调用闭包,它可以让变量值始终保存在内存中,即使外部的执行环境已经结束了。

    4、闭包的优缺点

    (1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

    (2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

  • 相关阅读:
    查看Oracle的redo日志切换频率
    MySQL 5.6 my.cnf 参数说明(转)
    MySQL性能优化之参数配置
    centos7安装mysql(MariaDB)
    centos6.5安装sendmail
    zabbix安装配置
    linux设置安全连接设置(私钥)
    linux本机root账户无法登录,但是远程ssh可登录
    ORACLE AWR
    maven 依赖(依赖范围,聚合,继承等)
  • 原文地址:https://www.cnblogs.com/xwkj/p/10087629.html
Copyright © 2011-2022 走看看