此文章是vip文章,如何查看?  

1,点击链接获取密钥 http://nicethemes.cn/product/view29882.html

2,在下方输入文章查看密钥即可立即查看当前vip文章


JavaScript 闭包 计数器困境

  • 时间:
  • 浏览:
  • 来源:互联网

关于全局和局部变量

JavaScript 变量包括有局部变量和全局变量。

如果变量定义在函数内部,则是局部变量,对于其它的函数或脚本代码是不可用的,全局和局部变量即使名称相同,但也是两个不同的变量,修改其中一个,不会对另外一个造成影响。

在变量声明时不使用 var 关键字,那它就是一个全局变量,即便它在函数内部定义。

JavaScript 计数器困境

在统计一些数值时,计数器通常需要在所有函数中可用,这时可以使用全局变量,函数设置计数器的递增

<script>
	var counter = 0; // 计数器初始值为 0
	function plusa(){
		counter += 5;   // 设置计数器的递增
		document.getElementsByTagName("body")[0].innerText = counter;
	}
	setInterval(plusa,1000)  // 每隔 1s 加 5
</script>

计数器数值在执行 plusa() 函数时发生变化,但问题来了,页面上的任何函数都能改变计数器,即便没有调用规定用于计数的 plusa() 函数,为了防止其它无关函数也改变 counter 计数器,可以在专门用于计数的函数 plusa() 内声明 counter ,这样就可以限定只有调用规定的 plusa() 函数才能修改计数器的值。

<script>
	function plusa(){
		var counter = 0; // 计数器初始值为 0, 但每次调用都会重新赋值为 0,导致计数结果永远是 5
		counter += 5;
		document.getElementsByTagName("body")[0].innerText = counter;
	}
	setInterval(plusa,1000)
</script>

此时,JavaScript 内嵌函数可以解决这个问题

JavaScript 内嵌函数

JavaScript 中,所有的函数都能访问它们上一层的作用域,包括全局变量,因此嵌套函数可以访问其上一层函数的变量。

<script>
	function result_all(){
		var counter = 0;
		function plusa(){ counter += 5; }  // 访问外层函数的 counter 变量
		plusa();  // 调用 plusa()
		document.getElementsByTagName("body")[0].innerText = counter;
	}
	setInterval(result_all,1000);  // 调用 result_all(),每隔 5s 执行一次 
</script>

由于每次访问 result_all() 函数的时候,都会经过 var counter = 0; 重新赋值了 counter,导致一直停在 5 ,无法实现计数功能,但如果能够在外部直接访问 plusa() 函数,那就能解决计数器困境。
关键在于 确保 var counter = 0; 只执行一次。

JavaScript 闭包

闭包是一个函数,可访问上一层函数作用域中的变量,即便上一层函数已经执行完关闭了

  • key:自调用函数的自调用作用,只执行一次。
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8">
</head>
<body>
</body>
<script>
	var result_all = (function (){
		var counter = 0;
		return function plusa(){ 
			counter += 5; // 访问外层函数的 counter 变量
			return document.getElementsByTagName("body")[0].innerText = counter;  // plusa() 函数的执行结果:实现计数
		}  
	})()
	console.log(result_all)  // 输出的是 plusa() 的函数对象
	setInterval(result_all,1000);  // 调用 result_all(),每隔 5s 执行一次,即直接调用了 plusa() 函数
</script>
</html>

变量 result_all 指定了自调用函数的返回值,即一个函数对象 plusa(),由于自调用函数只执行一次,counter 初始赋值为 0 后,就返回了函数表达式 plusa(),而此时的 result_all 变量就是函数 plusa() 的作用了,而由于 内嵌函数 可以访问函数上一层作用域的 counter 计数器,就实现了:

  • 防止无关脚本函数改变 counter,只有通过调用指定函数 plusa() 的方式进行计数
  • 计数器 counter 受匿名函数的作用域保护,只能通过指定的 result_all() 方法( 也就是内嵌函数 plusa() )修改。
  • 这个叫作 JavaScript 闭包,它使内部嵌套函数和其父函数的局部变量,变成外部可调用的,因此闭包使得其余函数拥有私有变量变得可能。

Reference

JavaScript 闭包

本文链接http://element-ui.cn/news/show-577017.aspx