成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

閉包不能吃...

stonezhu / 327人閱讀

摘要:什么是閉包閉包是函數(shù)廢話(huà)閉包還是一個(gè)可以訪(fǎng)問(wèn)函數(shù)中變量的函數(shù)。每個(gè)閉包都是引用自己詞法作用域內(nèi)的變量。每次調(diào)用其中一個(gè)計(jì)數(shù)器時(shí),通過(guò)改變這個(gè)變量的值,會(huì)改變這個(gè)閉包的詞法環(huán)境。然而在一個(gè)閉包內(nèi)對(duì)變量的修改,不會(huì)影響到另外一個(gè)閉包中的變量。

為什么要寫(xiě)深入理解

筆者并不是大神,只是一個(gè)在校的大三學(xué)生。開(kāi)始寫(xiě)深入理解系列是為了給js的一些重難點(diǎn)知識(shí)進(jìn)行梳理,而不是每次面試之前都將這些知識(shí)重新理解一遍。有理解的不對(duì)的,請(qǐng)賜教!事不宜遲,我們開(kāi)始吧。

什么是閉包

閉包是函數(shù)?。◤U話(huà))閉包還是一個(gè)可以訪(fǎng)問(wèn)函數(shù)中變量的函數(shù)。

function who(){
  let name="clong";
  function print(){
    return name;
  }
  return print;
}
let boy=who();
let myName=boy();
console.log(myName);//"clong"

開(kāi)始的定義可能會(huì)令你感覺(jué)晦澀難懂,看了上面的例子我們一起來(lái)理解一下。

分析

下面我們來(lái)分析一下上面的栗子。

首先我們聲明了一個(gè)函數(shù),這個(gè)函數(shù)包含了一個(gè)變量name和一個(gè)print函數(shù),執(zhí)行到return print的時(shí)候進(jìn)行返回。

緊接著我們?cè)谌肿饔糜蛳律艘粋€(gè)變量boy,繼續(xù)向該行后面看,有個(gè)who,接著我們遇到(),這時(shí)我們就會(huì)重新返回到上面查找who有沒(méi)有聲明。

進(jìn)入who體內(nèi),我們聲明了一個(gè)變量name并賦值為clong,然后申明了一個(gè)print函數(shù),接著我們返回print,此時(shí)print函數(shù)被銷(xiāo)毀,而boy保存著print函數(shù)的引用。

接著我們遇到myName,基本流程與上面的boy是差不多一致的,只不過(guò)這時(shí)我們的myName不是保存著一個(gè)函數(shù),而是保存了name的值(注意:這里name已經(jīng)被銷(xiāo)毀了,不信你可以在全局作用域下打印name的值看看!)。

有了上面的栗子,我們來(lái)看看下面這個(gè)栗子:

function createCounter() {
  let counter = 0
  const myFunction = function() {
      counter = counter + 1
      return counter
    }
    return myFunction
  }
  const increment = createCounter()
  const c1 = increment()
  const c2 = increment()
  const c3 = increment()
  console.log("example increment", c1, c2, c3)//1,2,3

思考一下,答案與你認(rèn)為的一樣嗎?是不是以為是1,1,1呢?先不要急,我們?cè)賮?lái)看看下面這個(gè)栗子。

var makeCounter = function() {
  var privateCounter = 0;
  function changeBy(val) {
    privateCounter += val;
  }
  return {
    increment: function() {
      changeBy(1);
    },
    decrement: function() {
      changeBy(-1);
    },
    value: function() {
      return privateCounter;
    }
  }  
};

var Counter1 = makeCounter();
var Counter2 = makeCounter();
console.log(Counter1===Counter2);
console.log(Counter1.value()); /* logs 0 */
Counter1.increment();
Counter1.increment();
console.log(Counter1.value()); /* logs 2 */
Counter1.decrement();
console.log(Counter1.value()); /* logs 1 */
console.log(Counter2.value()); /* logs 0 */

看看上面的栗子,你會(huì)不會(huì)疑惑?本質(zhì)上都是調(diào)用的私有函數(shù)的方法,為什么Counter1和Counter2的privateCounter就會(huì)完全不一樣呢?

筆者查看了很多資料,別人總結(jié)的要么就是將mdn上的解釋一貼,要么就是含糊其辭。

請(qǐng)注意兩個(gè)計(jì)數(shù)器 counter1 和 counter2 是如何維護(hù)它們各自的獨(dú)立性的。每個(gè)閉包都是引用自己詞法作用域內(nèi)的變量 privateCounter 。每次調(diào)用其中一個(gè)計(jì)數(shù)器時(shí),通過(guò)改變這個(gè)變量的值,會(huì)改變這個(gè)閉包的詞法環(huán)境。然而在一個(gè)閉包內(nèi)對(duì)變量的修改,不會(huì)影響到另外一個(gè)閉包中的變量?!狹DN

那么為什么對(duì)一個(gè)閉包的變量的改變不會(huì)影響到另一個(gè)閉包中的變量呢?我思考了很久,最后這樣解釋給自己聽(tīng):

前一個(gè)栗子中,我們的increment保存的是myFunction的引用和他的閉包(important:函數(shù)在創(chuàng)建的時(shí)候就會(huì)形成自己的作用域鏈)。了解過(guò)閉包的應(yīng)該都有保存在內(nèi)存中這個(gè)概念,那么我們這里沒(méi)得操作都是直接對(duì)閉包的操作,價(jià)值作用域的執(zhí)行順序(閉包=>父級(jí)=>...),每次都是從閉包中獲取,并且將修改的值保存在內(nèi)存中,自然是1,2,3!

那么后面一個(gè)栗子呢?我先姑且解釋看看(有不對(duì)的希望大??梢灾赋觯?函數(shù)中的變量都是私有的(包括函數(shù)),第二個(gè)栗子返回的是一個(gè)對(duì)象,然后我們后面的操作都是基于這個(gè)對(duì)象的屬性的操作,間接操作了內(nèi)部的私有方法并獲取了內(nèi)部的值。那么,回想一下new一個(gè)對(duì)象發(fā)生了什么?

創(chuàng)建一個(gè)空對(duì)象

將構(gòu)造函數(shù)的作用域賦給新對(duì)象,即將this只想新對(duì)象

講原型中的屬性添加到這個(gè)對(duì)象當(dāng)中

返回新對(duì)象

這個(gè)栗子不是正好跟上面的操作類(lèi)似嗎?如果還是不明白,我們假設(shè)makeCounter是一個(gè)Array對(duì)象,里面的private和changeBy是length和push內(nèi)部實(shí)現(xiàn)原理,返回一個(gè)新對(duì)象,并且給了你一些接口,而這個(gè)接口正好有push,使你可以進(jìn)行push操作,且僅限于該對(duì)象的私有屬性的方式。那么實(shí)例與實(shí)例的私有屬性或方法共有嗎?當(dāng)然不!神奇的利用閉包就實(shí)現(xiàn)了數(shù)據(jù)的私有和封裝了

用處

經(jīng)過(guò)了上面的分析,我們大概可以了解到閉包的一些用處了吧。

訪(fǎng)問(wèn)函數(shù)中的變量

函數(shù)屬性的私有化/封裝(PS:這一塊還涉及到原型鏈,下次再寫(xiě))

劣勢(shì)

這些也是耳熟能詳了!

性能問(wèn)題,一直暴露在內(nèi)存當(dāng)中,無(wú)法被垃圾回收機(jī)制回收,很有可能造成內(nèi)存泄漏!

場(chǎng)景

回調(diào)函數(shù)

頁(yè)面交互操作(同上?。?/p>

setTimeout(不也是回調(diào)函數(shù)嘛?。?/p>

數(shù)據(jù)私有和封裝

tips

仍然可以訪(fǎng)問(wèn)外部函數(shù)的中定義的變量即使外部函數(shù)被返回了

閉包存儲(chǔ)對(duì)外部函數(shù)中變量的引用,而不是值

閉包可以實(shí)現(xiàn)js的數(shù)據(jù)的封裝和私有化

參考資料

MDN/JS/閉包
Understand JavaScript Closures With Ease
I never understood JavaScript closures

博客地址

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/95366.html

相關(guān)文章

  • JavaScript:面試頻繁出現(xiàn)的幾個(gè)易錯(cuò)點(diǎn)

    摘要:針對(duì)于面向?qū)ο缶幊痰?。因?yàn)槊嫦驅(qū)ο缶褪轻槍?duì)對(duì)象例子中的守候來(lái)進(jìn)行執(zhí)行某些動(dòng)作。這就是閉包的用途之一延續(xù)變量周期。把變量放在閉包里面和放在全局變量里面,影響是一致的。 1.前言 這段時(shí)間,金三銀四,很多人面試,很多人分享面試題。在前段時(shí)間,我也臨時(shí)擔(dān)任面試官,為了大概了解面試者的水平,我也寫(xiě)了一份題目,面試了幾個(gè)前端開(kāi)發(fā)者。在這段時(shí)間里面,我在學(xué),在寫(xiě)設(shè)計(jì)模式的一些知識(shí),想不到的設(shè)計(jì)模式...

    VincentFF 評(píng)論0 收藏0
  • Javascript 面試中經(jīng)常被問(wèn)到的三個(gè)問(wèn)題!

    摘要:相反,在討論時(shí),面試中通常會(huì)提到三件事。而認(rèn)為最后一個(gè)參賽者說(shuō)了算,只要還能吃的,就重新設(shè)定新的定時(shí)器。試想,如果用戶(hù)的操作十分頻繁他每次都不等設(shè)置的時(shí)間結(jié)束就進(jìn)行下一次操作,于是每次都為該用戶(hù)重新生成定時(shí)器,回調(diào)函數(shù)被延遲了不計(jì)其數(shù)次。本文不是討論最新的 JavaScript 庫(kù)、常見(jiàn)的開(kāi)發(fā)實(shí)踐或任何新的 ES6 函數(shù)。相反,在討論 JavaScript 時(shí),面試中通常會(huì)提到三件事。我自己...

    chnmagnus 評(píng)論0 收藏0
  • Javascript 面試中經(jīng)常被問(wèn)到的三個(gè)問(wèn)題!

    摘要:相反,在討論時(shí),面試中通常會(huì)提到三件事。通過(guò)對(duì)事件對(duì)應(yīng)的回調(diào)函數(shù)進(jìn)行包裹以自由變量的形式緩存時(shí)間信息,最后用來(lái)控制事件的觸發(fā)頻率。而認(rèn)為最后一個(gè)參賽者說(shuō)了算,只要還能吃的,就重新設(shè)定新的定時(shí)器。 showImg(https://segmentfault.com/img/bVboH5x?w=1000&h=750); 想閱讀更多優(yōu)質(zhì)文章請(qǐng)猛戳GitHub博客,一年百來(lái)篇優(yōu)質(zhì)文章等著你! 本...

    PrototypeZ 評(píng)論0 收藏0
  • JavaScript之閉包

    摘要:而閉包的妙處在于,當(dāng)函數(shù)在執(zhí)行完畢后它的活動(dòng)對(duì)象不會(huì)被銷(xiāo)毀,因?yàn)槟涿瘮?shù)的作用域鏈仍然在引用函數(shù)的活動(dòng)對(duì)象它的作用域鏈會(huì)被銷(xiāo)毀。 一、閉包 閉包是指有權(quán)訪(fǎng)問(wèn)另一個(gè)函數(shù)作用域中的變量的函數(shù)。創(chuàng)建閉包的常用方式是,在一個(gè)函數(shù)內(nèi)部創(chuàng)建另一個(gè)函數(shù)。 請(qǐng)看以下代碼:我們?cè)赾reateComparisonFunction函數(shù)里創(chuàng)建了一個(gè)閉包 function createComparisonFun...

    Mr_houzi 評(píng)論0 收藏0
  • PHP閉包的理解與介紹

    摘要:閉包與函數(shù)真正的區(qū)別函數(shù)封裝一次多處調(diào)用。閉包只限于本方法使用,耦合度低到忽略。 看過(guò)許多關(guān)于PHP中閉包的講解,每個(gè)文檔想要表達(dá)的意思大體相同,但是理解起來(lái)很費(fèi)勁,我根據(jù)自身理解加以描述,有更好的理解請(qǐng)指出 眾所周知,大家都知道PHP的閉包是function () use (){}; 本文分為3步1:講解閉包的使用2:閉包實(shí)例3:閉包總結(jié) 1、講解閉包的使用1:閉包中的use使用-上...

    gotham 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<