与旋量群相关的三个基本概念:
(1)表达式的返回值不暗含URLvar的表达式会正式成为自上而下表达式; 在表达式中采用URLvar新闻稿的表达式是局部表达式。 局部表达式多于在表达式内部就可以出访到,在表达式外边是出访不出的。但在表达式内部能透过返回值链始终向下搜寻直至自上而下第一类,换句话说,表达式内部能出访表达式内部的表达式。
(2)表达式的存活周期性对自上而下表达式,其存活周期性是永久性的,假如积极主动封存那个自上而下表达式; 而对在表达式前用URLvar新闻稿的局部表达式,当选择退出表达式时,那些局部表达式会随著表达式调用完结而被封存。
个别情况:旋量群
从旋量群的两个经典之作应用领域说起
难题:不论空格键别的div,单厢弹出5。 其原因:onclick该事件是触发器促发的,当该事件被促发时,for循环式已然完结,这时表达式i的值已然经是5。 化解:在旋量群的协助下,把每天循环式的i值都半封闭出来。当该事件表达式顺著返回值链从内到外搜寻表达式i时,会先找出被半封闭在旋量群自然环境的i,空格键div时,会依次输入0,1,2,3,4。
类似示例:旋量群直接赋给数组
结果:result的每个元素都返回10。 说明:旋量群的返回值链有明显的副作用——旋量群总是获得内部表达式表达式的最终值。上面代码中,内部表达式产生两个表达式数组result并返回。表达式数组中的每个元素都是两个表达式,每个表达式都返回 i表达式。似乎每个表达式应该返回每天循环式的i值,即依次返回0到9,但事实是,每个表达式的返回结果都是10。这是因为每个内部表达式返回的是表达式i,而不是i在某个时刻的特定值,而i的返回值是整个内部表达式,当内部表达式执行完成后,i的值是10。 化解:在每个内部表达式的内部,再产生两个匿名表达式并返回。
结果:result依次返回0到9。 说明:(i)使得该层匿名表达式立即执行。 ###3、旋量群
有时候需要得到表达式内的局部表达式。如何从内部读取局部表达式?那就是在表达式的内部,再定义两个表达式。 旋量群是指有权出访另两个表达式返回值中表达式的表达式,创建旋量群的最常见的方式就是在两个表达式内创建另两个表达式,透过另两个表达式出访那个表达式的局部表达式,利用旋量群能突破作用链域,将表达式内部的表达式和方法传递到内部。① 旋量群的基本原理
后台执行自然环境中,旋量群的返回值链包含着自己的返回值、表达式的返回值和自上而下返回值。通常,表达式的返回值和表达式会在表达式执行完结后封存。但是,当表达式返回两个旋量群时,那个表达式的返回值将会始终在内存中保存到旋量群不存在为止。② 旋量群的特性表达式内再嵌套表达式。内部表达式能引用外层的参数和表达式。参数和表达式不会被垃圾回收机制回收。③ 旋量群的用途读取表达式内部的表达式。在上面的代码中,表达式f2就被包括在表达式f1内部,这时f1内部的所有局部表达式,对f2都是可见的。但是反过来就不行,f2内部的局部表达式,对f1就是不可见的。既然f2能读取f1中的局部表达式,那么只要把f2作为返回值,就能在f1内部读取它的内部表达式了。
旋量群就是能够读取其他表达式内部表达式的表达式。由于在Javascript语言中,多于表达式内部的子表达式就可以读取局部表达式,因此能把旋量群简单认知成”定义在两个表达式内部的表达式”。所以,在本质上,旋量群就是将表达式内部和表达式内部连接出来的一座桥梁。
result实际上就是旋量群f2表达式。它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,表达式f1中的局部表达式n始终保存在内存中,并没有在f1调用后被自动清除。其原因就在于f1是f2的父表达式,而f2被赋给了两个自上而下表达式,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用完结后,被垃圾回收机制回收。 (2)让表达式内部的表达式的值始终保持在内存中(延长局部表达式的寿命)
由于旋量群会使得表达式中的表达式都被保存在内存中,内存消耗很大,所以不能滥用旋量群,否则会造成网页的性能难题,在IE中可能导致内存泄露。化解方法是,在选择退出表达式之前,将不采用的局部表达式全部删除。换句话说,旋量群会引用内部表达式返回值,会占用更多的内存,过度采用旋量群,会导致性能难题。所以,仅当必要时才采用旋量群。对产生旋量群的表达式,采用后应该解除引用。 (3)自执行表达式+旋量群减少自上而下表达式污染(封装私有表达式)
var person = (function() { var_name = “Alice”; var _id = 16; return { getUserInfo: function() { return _name + “: ” + _id; } } })();//协助突破技术瓶颈,提升思维能力采用下划线来约定私有表达式_name和_age,它们被封装在旋量群产生的返回值中,内部是出访不出这三个表达式的,这就避免了对自上而下的命令污染。 ④ 旋量群的缺点: (1) 需要维护额外的返回值。 (2) 过渡采用旋量群会占用大量内存。4、this第一类在旋量群内采用this第一类将产生一些复杂的行为。this第一类的值基于表达式所在的执行自然环境在运行时决定:在自上而下表达式中采用时,this等于window(非严格模式)或undefined(严格模式);而当作为第一类的方法调用时,this等于那个第一类。
每个表达式一旦被调用,它将自动获得this和arguments三个表达式。两个内部表达式是不能直接从内部表达式出访到这三个表达式的。能透过将this对象存储在另两个表达式中来化解那个难题。把内部返回值中的this第一类保存在两个旋量群能够出访到的表达式里,就能让旋量群出访该第一类了。
var name =”The window”; var object = { name: “My object”, getName: function() { var that = this; return function() { return that.name; }; } }; alert(object.getName()());//输入:”My object”要让旋量群出访内部表达式的this和arguments第一类,能透过将它们的引用存储在另两个表达式中来完成。 5、内存泄漏采用旋量群的时候很容易造成循环式引用,若旋量群的返回值包含着一些DOM节点,这时候就有可能造成内存泄漏,但其实,这本身不是旋量群的难题,而是由于:BOM和DOM中的第一类是采用C++以COM第一类的方式实现的,而COM第一类的垃圾收集机制采用的是引用计数策略,在基于引用计数策略的垃圾回收机制中,若三个第一类之间形成了循环式引用,则这三个第一类都无法被回收。
匿名表达式保存了两个对element的引用,只要匿名表达式存在,element的引用数至少为1,它所占用的内存就永远不会被回收。
透过把element.id的两个副本保存在表达式中,并且在旋量群中引用该表达式消除了循环式引用,但是仅仅做到这一步还不能化解内存泄漏的难题,旋量群会引用包含表达式的所有活动第一类,包含element,即使旋量群不直接引用element,包含表达式的活动第一类中也仍然会保存两个引用,因此有必要把element元素设置为null,这样就能解除对DOM第一类的引用,确保正常回收其占用的内存。6、模仿块级返回值 JavaScript中没有直接的块级返回值。
采用旋量群能模仿块级返回值——创建并立即调用两个表达式,这样既能执行其中的代码,又不会在内存中留下对该表达式的引用。结果是内部表达式的所有表达式单厢立即被封存,假如将某些表达式赋值给了包含返回值(即内部返回值)中的表达式。 用作块级返回值的匿名表达式:将表达式新闻稿包含在一对圆括号中,表示它实际上是两个表达式表达式,紧随其后的另一对圆括号会立即调用那个表达式。
(function() { //这里是块级返回值; }) ();能采用匿名表达式表达式来模拟块级返回值,任何定义在匿名表达式中的表达式在匿名表达式执行完之后都将被封存,在匿名表达式外出访那些表达式将会产生错误。