什么是闭包?使用常见场景,优缺点?

2023-05-28 0 632

1. 甚么是旋量群?

非官方基本概念:旋量群是指无权出访另两个表达式codice中的表达式的表达式

标识符块:

function fn1() { var name = Fuleny return function() { console.log(name) } } var fn2 = fn1() fn2() // Fuleny

在前述标识符中,旋量群指的是return function() { console.log(name) }那个表达式。

那个表达式在fn1表达式作用域外部,因此能出访到表达式外部的表达式name,fn1表达式外部的codice由自上而下codice下的表达式fn2转交,初始化fn2就能同时实现在自上而下表达式下出访局部表达式中的表达式的值。

两个经典之作的循环式点选的范例:

<ul> <li>li_1</li> <li>li_2</li> <li>li_3</li> <li>li_4</li> </ul> var elements = document.getElementsByTagName(li), length = elements.length for (var i = 0; i < length; i++) { elements[i].onclick = function() { console.log(i); } } // 4 4 4 4

解答:

给每两个li标签绑定了click事件,但绑定的表达式的codice中没有表达式i,此时i为undefined,则解析引擎就会寻找父级的codice,父级codice中有i,但此时的i已经循环式完i已经赋值为4,所以每个li标签被点选时,控制台都会打印出4。这是codice的问题。

旋量群只能取得包含表达式中任何表达式的最后两个值。因为别忘了旋量群所保存的是整个表达式对象,而不是某个特殊的表达式。

接下来采用旋量群解决那个问题:

var elements = document.getElementsByTagName(li), length = elements.length for (var i = 0; i < length; i++) { elements[i].onclick = logLiIndex(i) } function logLiIndex(num) { return function() { console.log(num) } } // 0 1 2 3 // 也能直接采用匿名旋量群表达式for (var i = 0; i < length; i++) { elements[i].onclick = function(num){ return function() { console.log(num) } }(i) } for (var i = 0; i < length; i++) { (function() { element(i).onclick = function() { console.log(i) } })() }

如果不想采用过多的旋量群,当然采用块级codice也可解决:

for (let i = 0; i < length; i++) { elements[i].onclick = function() { console.log(i) } } // 0 1 2 3// 块级codice的到来,也让令人诟病的JS有了一丝生机,补上了JS的短板

2. 旋量群可被利用的常用情景

2.1 采用表达式引用方式的setTimeout初始化

原生的setTimeout传递的第两个表达式不能带参数

setTimeout(function(params) { console.log(params) }, 1000) // undefined

如果一段标识符想要通过setTimeout来初始化,那么它的第两个参数需要传递两个表达式对象的引用,第二个参数是需要延迟的毫秒数,但那个表达式对象的引用无法为将要被执行的对象提供参数。

但是能初始化两个表达式来返回两个外部表达式的初始化,将那个外部表达式对象的引用传递给setTimeout表达式。外部表达式需要的参数,外部表达式为传递给它。

function log(num) { return function() { console.log(`第${num}秒后打印`) } } setTimeout(log(2), 2000) // 第2秒后打印

2.2 回调

大部分我们所写的JS标识符中都是基于事件的——定义某种行为,然后添加到用户触发的事件之上(比如点选或者按键),我们的标识符通常作为回调:为响应事件而执行的表达式。

例如在页面上添加一种能调整字号的按钮:

body { font-family: Helvetica, Arial, sans-serif; font-size: 12px; } h1 { font-size: 1.5em; } h2 { font-size: 1.2em; }

由于采用的是相对单位,只需修改body中的font-size属性,其他元素也会相对调整。

function makeSizer(size) { return function() { document.body.style.fontSize = size + px } } var size12 = makeSizer(12) var size14 = makeSizer(14) var size16 = makeSizer(16) // 分别将他们添加到按钮的点选事件上 document.getElementById(size_12).onclick = size12 document.getElementById(size_14).onclick = size14 document.getElementById(size_16).onclick = size16 <a href=“#” id=“size_12”></a> <a href=“#” id=“size_14”></a> <a href=“#” id=“size_16”></a>

2.3 用旋量群模拟私有方法

编程语言中JAVA是支持将方法声明为私有的,而JavaScript没有这种原生支持,但能采用旋量群来模拟私有方法。私有方法不仅仅有利于限制对标识符的出访:还提供了管理自上而下命名空间的强大能力,避免了非核心的标识符弄乱了标识符的公共接口。

var Counter = (function() { var privateCounter = 0 // 私有表达式 function changBy(val) { privateCounter += val } return { intcrement: function() { // 三个旋量群共用两个词法语境 changBy(1) }, delcrement: function() { changBy(1) }, value: function() { return privateCounter } } })() console.log(Counter.value()) // 0 Counter.intcrement() Counter.intcrement() console.log(Counter.value()) // 2 Counter.delcrement() console.log(Counter.value()) // 1

能把那个表达式储存在另两个表达式makeCounter中并用它来创建多个计数器。

var makeCounter = (function() { var privateCounter = 0 function changBy(val) { privateCounter += val } return { intcrement: function() { changBy(1) }, delcrement: function() { changBy(1) }, value: function() { return privateCounter } } })() var Counter1 = makeCounter() var Counter2 = makeCounter() // 每个旋量群都是引用自己词法codice内的表达式privateCounter console.log(Counter1.value(), Counter2.value()) // 0 0 Counter1.intcrement() console.log(Counter1.value(), Counter2.value()) // 1 0

两个旋量群内对表达式的修改,不会影响另两个旋量群的表达式

以这种方式采用旋量群,提供了许多面向对象编程的相关好处——特别是数据隐藏和封装

3. 旋量群的优劣

优点:

表达式长期驻扎在内存中

避免自上而下表达式的污染

能定义私有属性和私有方法

旋量群的典型框架应该是jQuery,旋量群是JavaScript的一大特点,主要应用旋量群场合是为了:设计私有的方法和表达式。

这在做框架的时候体现更明

缺点:

常驻内存 会增大内存的采用量 采用不当会造成内存泄露

能改变父表达式外部表达式的值

旋量群有两个非常严重的问题,那是内存浪费问题,那个内存浪费不仅仅因为它常驻内存,更重要的是,对旋量群的采用不当会造成无效内存的产生

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务