Näen silloin tällöin ”sulkemiset”, ja yritin etsiä sitä, mutta Wiki ei anna selitystä, jota ymmärrän. Voisiko joku auta minua täällä?
Kommentit
- Jos tiedät Java / C # toivon, että tämä linkki auttaa- http://www.developerfusion.com/article/8251/the-beauty-of-closures/
- Sulkemisia on vaikea ymmärtää. Yritä napsauttaa kaikkia Wikipedia-artikkelin ensimmäisen virkkeen linkkejä ja ymmärtää ne artikkelit ensin.
- stackoverflow.com/questions/36636/what-is-a-closure
- Mitä ’ onko kuitenkin keskeinen ero sulkemisen ja luokan välillä? Okei, luokka, jossa on vain yksi julkinen menetelmä.
- @biziclop: Voit voisit matkia sulkemista luokalla (joka ’ s mitä Java-kehittäjien on tehtävä). Mutta ne ’ ovat yleensä hieman vähemmän sanallisia luoda ja et ei tarvitse hallita manuaalisesti sitä, mitä ’ tarvitset. (Vakavimmat lispersit esittävät samanlaisen kysymyksen, mutta pääsevät todennäköisesti siihen toiseen johtopäätökseen – että kielitason OO-tuki on tarpeetonta, kun sinulla on sulkemisia).
Vastaa
(Vastuuvapauslauseke: tämä on perusselitys; määritelmän suhteen yksinkertaistan hieman)
Yksinkertaisin tapa ajatella sulkemista on -toiminto, joka voidaan tallentaa muuttujana (kutsutaan nimellä ”ensimmäinen” -class-toiminto ”), jolla on erityinen kyky käyttää muita paikallisia muuttujia sille laajuudelle, johon se luotiin.
Esimerkki (JavaScript):
var setKeyPress = function(callback) { document.onkeypress = callback; }; var initialize = function() { var black = false; document.onclick = function() { black = !black; document.body.style.backgroundColor = black ? "#000000" : "transparent"; } var displayValOfBlack = function() { alert(black); } setKeyPress(displayValOfBlack); }; initialize();
Toiminnot 1 , jotka on määritetty document.onclick
ja displayValOfBlack
ovat sulkemisia. Voit nähdä, että molemmat viittaavat loogiseen muuttujaan black
, mutta muuttuja on määritetty funktion ulkopuolelle. Koska black
on paikallinen sille alueelle, jossa funktio määritettiin , muuttujan osoitin säilyy.
Jos laitat tämän HTML-sivulle:
- Napsauta vaihtaaksesi mustaksi
- Napsauta [enter] nähdäksesi ”tosi”
- Napsauta uudelleen, muuttuu takaisin valkoiseksi
- Napsauta [enter] nähdäksesi ”epätosi”
Tämä osoittaa, että molemmilla on pääsy samaan black
, ja sitä voidaan käyttää tilan tallentamiseen ilman mitään kääreobjektia.
Kutsu setKeyPress
on osoittaa, kuinka funktio voidaan siirtää aivan kuten mikä tahansa muuttuja. Sulkussa säilytetty laajuus on edelleen se, jossa funktio määritettiin.
Sulkimet ovat yleisesti käytetään tapahtumankäsittelijöinä, erityisesti JavaScriptissä ja ActionScriptissä. Sulkimien hyvä käyttö auttaa sinua sitomaan muuttujia epäsuorasti tapahtumankäsittelijöihin ilman, että sinun on luotava objektikääre. Huolimaton käyttö johtaa kuitenkin muistivuotoihin (esimerkiksi silloin, kun käyttämätön mutta säilytetty tapahtumankäsittelijä on ainoa asia, joka pitää kiinni suurista muistin esineistä, etenkin DOM-objekteista, estäen roskien keräämisen).
1: Itse asiassa kaikki JavaScriptin toiminnot ovat sulkemisia.
Kommentit
- Luin vastaustasi tunsin hehkulampun syttyvän mielessäni. Kiitos paljon! 🙂
- Koska
black
on ilmoitettu funktion sisällä, ei ’ t tuhoutuisi pinon purkautuessa. ..? - @gablin, se on ainutlaatuista kielillä, joilla on sulkeminen. Kaikki roskien keräyskielet toimivat samalla tavalla – kun esineeseen ei enää viitata, se voidaan tuhota. Aina kun funktio luodaan JS: ssä, paikallinen ulottuvuus on sidottu tähän toimintoon, kunnes funktio tuhoutuu.
- @gablin, tämä ’ on hyvä kysymys. En usko ’, että he eivät voi ’ t & mdash; mutta otin esille vain roskakorin, koska sitä mitä JS käyttää ja että ’ s mitä sinä näytit tarkoittavan, kun sanoit ” Koska
black
ilmoitetaan funktion sisällä, joka ei tuhoutuisi ’ t ”. Muista myös, että jos ilmoitat objektin funktiossa ja määrität sen sitten muuttujalle, joka elää jossakin muualla, objekti säilytetään, koska siihen on muita viittauksia. - Objective-C (ja C kohdassa clang) tukee lohkoja, jotka ovat olennaisesti sulkimia, ilman roskien keräystä. Se vaatii ajonaikaisen tuen ja jonkin verran manuaalista puuttumista muistinhallintaan.
vastaus
Sulkeminen on pohjimmiltaan vain erilainen tapa tarkastella kohdetta. Objekti on tietoja, joihin on sidottu yksi tai useampi toiminto. Sulkeminen on toiminto, johon on sidottu yksi tai useampi muuttuja. Nämä kaksi ovat periaatteessa identtisiä ainakin toteutustasolla. Todellinen ero on siinä, mistä ne tulevat.
Objektikeskeisessä ohjelmoinnissa ilmoitat objektiluokan määrittelemällä sen jäsenmuuttujat ja sen menetelmät (jäsenfunktiot) etupuolelle ja sitten luomalla että luokka. Jokaisessa instanssissa on kopio jäsentiedoista, jonka rakentaja on alustanut. Sinulla on sitten objektityyppinen muuttuja ja välität sen tietona, koska painopiste on sen luonteessa datana.
Toisaalta suljetessa objekti ei ole määritelty etukäteen kuten objektiluokka tai ilmentynyt koodissasi olevan konstruktorin kutsun kautta. Sen sijaan kirjoitat sulkemisen toisen funktion sisälle. Sulkeminen voi viitata mihin tahansa ulomman funktion paikalliseen muuttujaan, ja kääntäjä havaitsee sen ja siirtää nämä muuttujat ulomman funktion pinotilasta sulkemisen piilotetun objektin ilmoitukseen. Sinulla on sitten sulkutyyppinen muuttuja. , ja vaikka se on pohjimmiltaan esine hupun alla, siirrät sen ympärille funktion viitteenä, koska painopiste on sen luonteessa funktiona.
Kommentit
- +1: Hyvä vastaus. Voit nähdä sulkemisen objektina, jolla on vain yksi menetelmä, ja mielivaltaisen objektin kokoelmana sulkeutumista joihinkin yleisiin taustalla oleviin tietoihin (objekti ’ s -muuttujat). Mielestäni nämä kaksi näkemystä ovat melko symmetrisiä.
- Erittäin hyvä vastaus. Se todella selittää sulkemisen oivalluksen.
- @Mason Wheeler: Mihin sulkemistiedot tallennetaan? Pinoa kuin funktio? Tai kasassa kuin esine?
- @RoboAlex: Kasassa, koska se ’ on esine, joka näyttää funktiolta .
- @RoboAlex: Sulkemisen ja sen siepattujen tietojen tallennuspaikka riippuu toteutuksesta. C ++: ssa se voidaan tallentaa kasaan tai pinoon.
Vastaus
Termi sulkeminen tulee siitä, että koodilla (lohko, funktio) voi olla vapaita muuttujia, jotka ovat suljettu (eli sidottu arvoon) ympäristöstä, jossa koodilohko on määritelty.
Otetaan esimerkiksi Scala-funktion määritelmä :
def addConstant(v: Int): Int = v + k
Funktion rungossa on kaksi nimeä (muuttujaa) v
ja k
osoittaa kaksi kokonaislukua. Nimi v
on sidottu, koska se ilmoitetaan funktion addConstant
argumenttina (tarkastelemalla funktion ilmoitusta tiedämme, että v
määritetään arvo, kun toiminto käynnistetään). Nimi k
on vapaa kirjoittanut funktion addConstant
, koska funktio ei sisällä aavistustakaan siitä, mikä arvo k
on sidottu (ja miten).
Jotta voimme arvioida puhelun, kuten:
val n = addConstant(10)
meidän on määritettävä k
arvo, joka voi tapahtua vain, jos nimi k
määritetään kontekstissa, jossa addConstant
on määritelty. Esimerkki:
def increaseAll(values: List[Int]): List[Int] = { val k = 2 def addConstant(v: Int): Int = v + k values.map(addConstant) }
Nyt kun olemme määrittäneet addConstant
kontekstissa, jossa k
on määritelty, addConstant
on tullut suljin , koska kaikki sen vapaat muuttujat ovat nyt suljettu (sidottu arvoon): addConstant
voi voidaan kutsua ja välittää kuin se olisi funktio. Huomaa, että vapaa muuttuja k
on sidottu arvoon, kun sulkeminen on määritelty , kun taas argumenttimuuttuja v
on sidottu, kun sulkeminen on kutsuttu .
Sulkeminen on siis periaatteessa toiminto tai koodilohko, joka voi käyttää ei-paikallisia arvoja vapaiden muuttujiensa kautta sen jälkeen, kun konteksti on sitonut ne.
Jos käytä suljinta vain, kun voit tehdä siitä tuntemattoman , esim.
def increaseAll(values: List[Int]): List[Int] = { val k = 2 values.map(v => v + k) }
Huomaa, että funktio, jossa ei ole vapaita muuttujia, on sulkeutumisen erityistapaus (tyhjien vapaiden muuttujien joukko). Vastaavasti anonyymi funktio on nimettömän sulkemisen erikoistapaus div id = ”aeb5abc95a”>
, eli anonyymi funktio on nimettömä sulkeminen ilman vapaita muuttujia.
Kommentit
- Tämä sopii hyvin sulkeisiin ja avoimiin kaavoihin logiikassa. Kiitos vastauksestasi.
- @RainDoctor: Ilmaiset muuttujat määritellään logiikkakaavoissa ja lambda calculus -lausekkeissa samalla tavalla: lambda-lausekkeen lambda toimii kuten kvantisoija logiikkakaavoissa, joissa on vapaita / sidottuja muuttujia .
vastaus
Yksinkertainen selitys JavaScriptissä:
var closure_example = function() { var closure = 0; // after first iteration the value will not be erased from the memory // because it is bound with the returned alertValue function. return { alertValue : function() { closure++; alert(closure); } }; }; closure_example();
alert(closure)
käyttää aiemmin luotua arvon closure
. Palautetun alertValue
-funktion nimitila liitetään nimitilaan, jossa muuttuja closure
asuu. Kun poistat koko toiminnon, muuttujan closure
arvo poistetaan, mutta siihen asti toiminto alertValue
pystyy aina lukemaan / kirjoittamaan muuttujan arvon closure
.
Jos suoritat tämän koodin, ensimmäinen iterointi antaa arvon 0 muuttujalle closure
ja kirjoita funktio uudeksi:
var closure_example = function(){ alertValue : function(){ closure++; alert(closure); } }
Ja koska alertValue
tarvitsee paikallisen muuttujan closure
toiminnon suorittamiseksi, se sitoutuu aiemmin määritetyn paikallisen muuttujan closure
arvoon.
Ja nyt joka kerta, kun soitat closure_example
-funktio, se kirjoittaa muuttujan closure
kasvavan arvon, koska alert(closure)
on sidottu.
closure_example.alertValue()//alerts value 1 closure_example.alertValue()//alerts value 2 closure_example.alertValue()//alerts value 3 //etc.
Kommentit
- kiitos, en ’ t testaa koodi =) kaikki näyttää nyt olevan kunnossa.
Vastaus
”Sulkeminen” on , pohjimmiltaan jotkut paikalliset osavaltiot ja koodit yhdistettynä paketiksi. Tyypillisesti paikallinen tila tulee ympäröivästä (sanallisesta) laajuudesta ja koodi on (olennaisesti) sisäinen toiminto, joka sitten palautetaan ulkopuolelle. Sulkeminen on sitten yhdistelmä siepattuja muuttujia, jotka sisäinen toiminto näkee, ja sisäisen toiminnon koodia.
Se on yksi niistä asioista, jota on valitettavasti vähän vaikea selittää olla tuntematon.
Yksi analogia, jota käytin menestyksekkäästi aiemmin, oli ”kuvitella, että meillä on jotain, jota kutsumme” kirjaksi ”, huoneen sulkemisessa,” kirja ”on kopio siellä, nurkassa TAOCP: n, mutta pöydän sulkemisen yhteydessä se on Dresdenin tiedostojen kirjan kopio. Joten riippuen siitä, mihin sulkemiseen olet, koodi ”anna minulle kirja” johtaa erilaisiin asioihin. ”
Kommentit
- Unohdit tämän: fi.wikipedia.org/wiki/Closure_(computer_programming) vastauksessasi.
- Ei, olen päättänyt olla sulkematta sivua.
- ” Tila ja toiminto. ”: Voiko C-funktiota, jolla on
static
paikallinen muuttuja, pitää sulkemisena? liittyykö Haskelliin tila? - @Giorgio Haskellin sulkeutumiset sulkevat (uskon) niiden leksikaalisen laajuuden argumentit, jotka ne ’ määrittelevät, joten minä ’ d sano ” kyllä ” (vaikkakaan en tunne Haskellia). Staattisella muuttujalla varustettu AC-toiminto on parhaimmillaan hyvin rajoitettu sulku (haluat todella pystyä luomaan useita sulkeutumisia yhdestä toiminnosta paikallisen muuttujan
static
avulla. täsmälleen yhden). - Esitin tämän kysymyksen tarkoituksella, koska mielestäni C-funktio, jossa on staattinen muuttuja, ei ole suljin: staattinen muuttuja määritetään paikallisesti ja tunnetaan vain sulkimen sisällä, se ei pääse ympäristö. En myöskään ole 100-prosenttisesti varma, mutta muotoilisin lausuntosi toisin päin: Sulkumekanismin avulla luodaan erilaisia toimintoja (funktio on sulkemismääritelmä + sitova sen vapaita muuttujia varten. ul>
vastaus
Sulkemisen merkitystä on vaikea määritellä määrittelemättä ”valtion” käsitettä.
Pohjimmiltaan , kielellä, jolla on täydellinen leksikaalinen ulottuvuus ja joka käsittelee toimintoja ensimmäisen luokan arvoina, tapahtuu jotain erityistä. Jos tekisin jotain seuraavista:
function foo(x) return x end x = foo
Muuttuja x
ei viittaa vain function foo()
, mutta se viittaa myös tilaan foo
, joka jätettiin edellisen kerran, kun se palasi. Todellinen taika tapahtuu, kun foo
: llä on muita toimintoja, jotka on määritelty tarkemmin sen soveltamisalaan; se on kuin oma miniympäristö (aivan kuten ”normaalisti” määritämme toiminnot globaalissa ympäristössä).
Toiminnallisesti se voi ratkaista monia samoja ongelmia kuin C ++ (C?) ”staattinen” avainsana, joka säilyttää paikallisen muuttujan tilan useiden toimintokutsujen aikana; se on kuitenkin enemmän kuin saman periaatteen (staattisen muuttujan) soveltaminen funktioon, koska funktiot ovat ensiluokkaisia arvoja; sulkeminen lisää tukea koko funktion tallennettavaan tilaan (ei mitään tekemistä C ++: n staattisten toimintojen kanssa).
Funktioiden käsitteleminen ensimmäisen luokan arvona ja tuen lisääminen sulkemisille tarkoittaa myös sitä, että muistissa voi olla useita toimintoja (samanlainen kuin luokissa). Tämä tarkoittaa sitä, että voit käyttää sama koodi tarvitsematta nollata toiminnon tilaa, kuten vaaditaan käsiteltäessä C ++ – staattisia muuttujia toiminnon sisällä (voi olla väärässä tässä?).
Tässä on joitain Luan sulkemistuen testauksia .
--Closure testing --By Trae Barlow -- function myclosure() print(pvalue)--nil local pvalue = pvalue or 10 return function() pvalue = pvalue + 10 --20, 31, 42, 53(53 never printed) print(pvalue) pvalue = pvalue + 1 --21, 32, 43(pvalue state saved through multiple calls) return pvalue end end x = myclosure() --x now references anonymous function inside myclosure() x()--nil, 20 x() --21, 31 x() --32, 42 --43, 53 -- if we iterated x() again
tulokset:
nil 20 31 42
Se voi olla hankalaa, ja se todennäköisesti vaihtelee kielestä kieleksi, mutta Luassa näyttää siltä, että aina kun funktio suoritetaan, sen tila nollataan. Sanon tämän, koska yllä olevan koodin tulokset olisivat erilaiset, jos olisimme yhteydessä -toiminto / tila suoraan (anonyymin funktion kautta, jonka se palauttaa), koska pvalue
palautettaisiin takaisin arvoon 10; mutta jos pääsemme myclosure-tilaan x: n (nimettömän funktion) kautta, voit nähdä, että pvalue
on elossa ja hyvin jossain muistissa. Epäilen, että siinä on ehkä hieman enemmän joku osaa paremmin selittää toteutuksen luonteen.
PS: En tiedä nuolla C ++ 11: tä (muuta kuin mitä edellisissä versioissa), joten huomaa, että tämä ei ole vertailu C ++ 11: n ja Luan sulkemisten välillä. Myös kaikki ”viivat”, jotka on vedetty Lua: sta C ++: een, ovat yhtäläisyyksiä, koska staattiset muuttujat ja sulkut eivät ole 100% samanlaisia; vaikka niitä käytetään joskus vastaavien ongelmien ratkaisemiseen.
Asia, josta en ole varma, on yllä olevassa koodiesimerkissä, pidetäänkö anonyymia vai korkeamman asteen funktiota sulkemisena?
Vastaus
Sulkeminen on toiminto, johon liittyy tila:
Perlissä luot tällaisia sulkemisia:
#!/usr/bin/perl # This function creates a closure. sub getHelloPrint { # Bind state for the function we are returning. my ($first) = @_;a # The function returned will have access to the variable $first return sub { my ($second) = @_; print "$first $second\n"; }; } my $hw = getHelloPrint("Hello"); my $gw = getHelloPrint("Goodby"); &$hw("World"); // Print Hello World &$gw("World"); // PRint Goodby World
Jos tarkastelemme C ++: n tarjoamia uusia toimintoja.
Sen avulla voit myös sitoa nykyisen tilan objektiin:
#include <string> #include <iostream> #include <functional> std::function<void(std::string const&)> getLambda(std::string const& first) { // Here we bind `first` to the function // The second parameter will be passed when we call the function return [first](std::string const& second) -> void { std::cout << first << " " << second << "\n"; }; } int main(int argc, char* argv[]) { auto hw = getLambda("Hello"); auto gw = getLambda("GoodBye"); hw("World"); gw("World"); }
Vastaus
Tarkastellaan yksinkertaista toimintoa:
function f1(x) { // ... something }
Tätä toimintoa kutsutaan ylätason funktioksi, koska sitä ei ole sisäkkäin missään muussa toiminnossa. Jokainen JavaScript-funktio liittää itsensä luetteloon objekteista, joita kutsutaan ” Scope Chain ”. Tämä laajuusketju on järjestetty esineiden luettelo Näiden objektien joukko määrittelee joitain muuttujia.
Ylätason toiminnoissa laajuusketju koostuu yhdestä objektista, globaalista objektista. Esimerkiksi yllä olevalla funktiolla f1
on laajuusketju, jossa on yksi objekti, joka määrittelee kaikki globaalit muuttujat. (huomaa, että termi ”objekti” tässä ei tarkoita JavaScriptiä, se on vain toteutuksen määrittelemä objekti, joka toimii muuttujasäiliönä, josta JavaScript voi ”etsiä” muuttujia.)
Kun tämä toiminto käynnistetään, JavaScript luo jotain nimeltään ”Aktivointiobjekti” ja laittaa sen soveltamisalaketjun yläosaan. Tämä objekti sisältää kaikki paikalliset muuttujat (esimerkiksi x
täällä) .Siksi laajennusketjussa on nyt kaksi objektia: ensimmäinen on aktivointikohde ja sen alla globaali objekti.
Huomaa erittäin huolellisesti, että nämä kaksi objektia laitetaan soveltamisalaketjuun Eri kertaa. Globaali objekti asetetaan, kun funktio on määritelty (ts. kun JavaScript jäsentää funktion ja loi funktio-objektin) ja aktivointiobjekti tulee, kun toiminto kutsutaan.
Joten, tiedämme nyt tämän:
- Jokaisella funktiolla on liitetty laajuusketju
- Kunfunktio on määritelty (kun funktio-objekti luodaan), JavaScript tallentaa toimintoketjun kyseisellä funktiolla.
- Ylimmän tason funktioissa laajuusketju sisältää vain globaalin objektin funktion määrittelyhetkellä ja lisää uuden aktivointikohde ylhäällä kutsuhetkellä
Tilanne on mielenkiintoinen, kun käsittelemme sisäkkäisiä toimintoja. Joten, luo ”s” sellaisen:
function f1(x) { function f2(y) { // ... something } }
Kun f1
määritetään, saamme sille laajuusketjun, joka sisältää vain globaali objekti.
Nyt kun f1
kutsutaan, f1
-alueen ketju saa aktivointikohteen. Tämä aktivointikohde sisältää muuttujan x
ja muuttujan f2
, joka on funktio. Huomaa, että f2
määritellään.Tästä syystä JavaScript tallentaa tässä vaiheessa myös uuden laajuusketjun f2
: lle. Tätä sisäistä toimintoa varten tallennettu laajuusketju on nykyinen voimassa oleva ketju. Nykyinen laajuus ketju on käytännössä f1
”s. Siksi f2
” laajuusketju on f1
”s nykyinen laajuusketju – joka sisältää f1
-aktivointikohteen ja globaali objekti.
Kun f2
kutsutaan, se saa sen oman aktivointikohteen, joka sisältää y
, lisätty sen soveltamisalaketjuun, joka sisältää jo aktivointikohteen f1
ja globaalin objektin.
Jos kohdassa f2
, sen laajuusketju sisältäisi kolme objektia määrittelyhetkellä (2 aktivointikohtaa kahdesta ulkoisesta toiminnosta ja globaalin objektin) ja 4 kutsuajankohtana.
Joten, nyt me alamme ja tarkista, miten laajuusketju toimii, mutta emme ole vielä puhuneet sulkemisista.
Funktio-objektin ja laajuuden (muuttuvan sidonnan joukko) yhdistelmä jossa funktion muuttujat on ratkaistu, kutsutaan tietojenkäsittelytieteen kirjallisuudessa – JavaScript on lopullinen opas, kirjoittanut David Flanagan
Useimmat toiminnot kutsutaan käyttämällä samaa laajuusketjua, joka oli voimassa, kun funktio määritettiin, eikä sillä ole väliä, että kyseessä on sulkeminen. Sulkemisista tulee mielenkiintoisia, kun niihin vedotaan eri laajuusketjussa kuin se, joka oli voimassa, kun ne määriteltiin. Tämä tapahtuu yleisimmin, kun sisäkkäinen funktio-objekti palautetaan funktiosta, johon se määritettiin.
Kun funktio palaa, aktivointikohde poistetaan laajuusketjusta. Jos sisäkkäisiä toimintoja ei ollut, aktivointikohteeseen ei ole enää viitteitä ja se kerää roskat. Jos sisäkkäisiä toimintoja oli määritelty, jokaisella näistä toiminnoista on viittaus laajuusketjuun ja kyseinen ketju viittaa aktivointiobjektiin.
Jos nämä sisäkkäiset funktiot-objektit pysyivät kuitenkin ulkoisessa toiminnossaan, sitten he itse kerätään roskat yhdessä aktivointikohteen kanssa, johon ne viittasivat. Mutta jos funktio määrittää sisäkkäisen funktion ja palauttaa sen tai tallentaa sen omaisuuteen jonnekin, sisäkkäiseen toimintoon tulee olemaan ulkoinen viite. Se ei ole roskia, eikä aktivointikohde, johon se viittaa, ei myöskään ole roskaa.
Yllä olevassa esimerkissämme emme palauta f2
kohteesta f1
, joten kun puhelu f1
palaa, sen aktivointiobjekti poistetaan sen ketjusta ja roskat kerätään. Mutta jos meillä olisi jotain tällaista:
function f1(x) { function f2(y) { // ... something } return f2; }
Täällä palaavalla f2
on laajuusketju, joka sisältää aktivointiobjektin f1
, ja siksi sitä ei kerätä roskiin. Jos kutsumme tässä vaiheessa f2
, se voi käyttää f1
”-muuttujaa x
vaikka olemmekin f1
ulkopuolella.
Tästä syystä voimme nähdä, että funktio pitää sen laajuusketjunsa mukana ja laajuusketjun kanssa tulevat kaikki ulkoisten toimintojen aktivointikohteet. Tämä on sulkemisen ydin. Sanomme, että JavaScriptin toiminnot ovat ”leksikaalisesti rajatut” , mikä tarkoittaa, että ne tallentavat aktiivisen laajuuden, kun ne määriteltiin, toisin kuin laajuus, joka oli aktiivinen, kun heitä kutsuttiin.
On olemassa useita tehokkaita ohjelmointitekniikoita, joihin sisältyy sulkeminen, kuten yksityisten muuttujien lähentäminen , tapahtumavetoinen ohjelmointi, osittainen sovellus jne.
Huomaa myös, että kaikki tämä koskee kaikkia kieliä, jotka tukevat sulkemisia. Esimerkiksi PHP (5.3+), Python, Ruby jne.
Vastaa
Sulkeminen on kääntäjän optimointi (alias syntaktinen sokeri?). Jotkut ihmiset ovat kutsuneet tätä myös köyhän ihmisen esineeksi .
Katso Eric Lippertin vastaus : (ote alla)
Kääntäjä luo seuraavanlaisen koodin:
private class Locals { public int count; public void Anonymous() { this.count++; } } public Action Counter() { Locals locals = new Locals(); locals.count = 0; Action counter = new Action(locals.Anonymous); return counter; }
Onko sinulla järkeä?
Pyysit myös vertailuja. Sekä VB että JScript luovat sulkemiset melkein samalla tavalla.
Kommentit
- Tämä vastaus on CW, koska en ansaitse pisteitä Ericille ’ ’ s hyvä vastaus.Äänestä sitä mielestäsi sopivaksi. HTH
- -1: Selityksesi on liian juurikas C #: ssä. Sulkemista käytetään monilla kielillä, ja se on paljon enemmän kuin syntaktinen sokeri näillä kielillä, ja se kattaa sekä toiminnon että tilan.
- Ei, sulkeminen ei ole vain ” kääntäjän optimointi ” eikä syntaktinen sokeri. -1