他们都晓得两个基本概念。
在JS之中,两个表达式能出访其外部的表达式天然资源。
两个众所周知的标识符
但下列此种情形会手忙脚乱。
function m1(){ var a = 100; console.log(a++); } function m2(){ console.log(a++); //这儿无法出访a }假如,他们想在m2的返回值里,出访m1里的表达式,就像上面这种:
具体来说,他们能在m1的外部建立两个表达式m3
function m1(){ var a = 100; function m3(){ console.log(a++); } }m3能正常出访a,接下来他们增加两个return操作。
function m1(){ vara =100; return function m3(){ console.log(a++); } }既然有了返回值,那他们不妨接收一下,继续编写标识符如下:
function m1(){ var a = 100; return function m3(){ console.log(a++); } } var _m3 = m1();他们执行了表达式m1, 并将返回值赋值给_m3,
那么目前_m3和m3表达式是等价的,即它们是同两个表达式。
有了_m3,一切都好办了。他们继续编写标识符
function m1(){ var a = 100; return function m3(){ console.log(a++); } }var _m3 = m1(); function m2(){ _m3(); }因为_m3是全局表达式,因此m2能调用_m3
也就等价于m2间接的,出访到了表达式a
通常,他们管m3,叫做两个『 旋量群表达式 』
上面列举几个常见的旋量群场景:
01
for(var i=0; i<list.length; i++){ var item = list[i]; item.onclick = (function(num){ return function(){ //…… } })(i); }02
function (){ var that = this; setTimeout(function(){ //…… },2000) }03
function User(){ var _age = 0; this.getAge = function(){ return _age; } this.setAge = function(age){ this._age = age; } }04
(function(){ var cache = […]; return { get : function(){ //… } }; })()05
(function(){ var t = null; return function(){ if(!t){ t = create(); } } })()为了创造旋量群,有时候会写表达式自调用
能不这么麻烦么??
当然,那就是使用let。
例如
for(let i=0; i<list.length; i++){ letitem = list[i]; item.onclick =function(){ console.log(i); //观察表达式i的值 }; }关于旋量群的疑问
当表达式m1执行完成的时候,外部的表达式a,理论上应该被回收掉了。
可是为甚么表达式a依然能被出访呢?
主要是因为,m3还在引用它
垃圾回收器显然不会回收两个依然被引用的表达式。
除非这个表达式,已经无人引用,即是说,它已经无法再内存里被找到。
此时才能当做垃圾处理。
不过m3能出访表达式a此种规则,并不是在所有编程语言里都生效的。因此,这也算是JS的特性之一。