Vra

Ek het'n vraag gevra oor Currying en sluitings genoem.Wat is'n sluiting?Hoe hou dit verband met currying?

Was dit nuttig?

Oplossing

Veranderlike omvang

Wanneer jy verklaar'n plaaslike veranderlike, wat veranderlike het'n omvang.Oor die algemeen, plaaslike veranderlikes bestaan slegs binne die blok of funksie in wat jy verklaar hulle.

function() {
  var a = 1;
  console.log(a); // works
}    
console.log(a); // fails

As ek probeer om toegang tot'n plaaslike veranderlike, die meeste tale sal kyk vir dit in die huidige omvang, dan deur die ouer bestekke totdat hulle bereik die wortel omvang.

var a = 1;
function() {
  console.log(a); // works
}    
console.log(a); // works

Wanneer'n blok of funksie is gedoen met, sy plaaslike veranderlikes is nie meer nodig nie en is gewoonlik geblaas uit van die geheue.

Dit is hoe ons normaalweg verwag dat dinge om te werk.

'n sluiting is'n aanhoudende plaaslike veranderlike omvang

'n sluiting is'n aanhoudende omvang wat tans op die plaaslike veranderlikes, selfs nadat die kode uitvoering het verskuif van daardie blok.Tale wat ondersteun sluiting (soos JavaScript, Swift, en Ruby) sal toelaat dat jy om tred te hou'n verwysing na'n omvang (insluitend sy ouer bestekke), selfs na afloop van die blok waarin die veranderlikes is verklaar het klaar die uitvoering, op voorwaarde dat jy hou'n verwysing na wat blok of funksie iewers.

Die omvang voorwerp en al sy plaaslike veranderlikes is wat gekoppel is aan die funksie en sal voortduur so lank as wat die funksie voortduur.

Dit gee ons funksie oordraagbaarheid.Ons kan verwag dat enige veranderlikes wat in omvang toe die funksie is die eerste keer gedefinieer om stil te wees in omvang toe ons later noem die funksie, selfs as ons noem die funksie in'n heeltemal ander konteks.

Byvoorbeeld

Hier is'n baie eenvoudige voorbeeld in JavaScript wat illustreer die punt:

outer = function() {
  var a = 1;
  var inner = function() {
    console.log(a);
  }
  return inner; // this returns a function
}

var fnc = outer(); // execute outer to get inner 
fnc();

Hier het ek gedefinieer het'n funksie binne'n funksie.Die binneste funksie winste toegang tot al die buitenste funksie is plaaslike veranderlikes, insluitend a.Die veranderlike a is in die ruimte vir die binneste funksie.

Gewoonlik wanneer'n funksie uitgange, al sy plaaslike veranderlikes is weg geblaas.Maar, as ons terugkeer van die binneste funksie en wys dit aan'n veranderlike fnc so dat dit voortduur na outer het opgewonde, al die veranderlikes wat in omvang toe inner is gedefinieer ook voortduur.Die veranderlike a gesluit is oor-dit is binne'n sluiting.

Let daarop dat die veranderlike a is heeltemal privaat te fnc.Hierdie is'n manier van die skep van private veranderlikes in'n funksionele programmeertaal soos JavaScript.

As jy dalk in staat wees om te raai, toe ek die oproep fnc() dit druk die waarde van a, wat is "1".

In'n taal sonder sluiting, die veranderlike a sou gewees vullis versamel en weggegooi wanneer die funksie outer opgewonde.Die roeping van fnc sou gegooi het'n fout, want a nie meer bestaan nie.

In JavaScript, die veranderlike a voortduur omdat die veranderlike omvang is geskep word wanneer die funksie is die eerste verklaar en te bly vir so lank as wat die funksie gaan voort om te bestaan.

a behoort aan die omvang van die outer.Die omvang van die inner het'n ouer wyser om die omvang van outer. fnc is'n veranderlike wat punte te inner. a voortduur so lank as wat fnc voortduur. a binne-in die sluiting.

Ander wenke

Ek sal 'n voorbeeld (in JavaScript) gee:

function makeCounter () {
  var count = 0;
  return function () {
    count += 1;
    return count;
  }
}

var x = makeCounter();

x(); returns 1

x(); returns 2

...etc...

Wat hierdie funksie, makeCounter, doen, is dit 'n funksie, wat ons x het genoem, wat sal tel by een elke keer as sy genoem terugkeer. Sedert ons nie die verskaffing van enige parameters om x dit een of ander manier die telling moet onthou. Dit weet waar om dit te vind wat gebaseer is op wat leksikale bestekopname genoem - dit moet kyk na die plek waar dit gedefinieer ter waarde vind. Hierdie "verborge" waarde is wat 'n sluiting genoem.

Hier is my currying voorbeeld weer:

function add (a) {
  return function (b) {
    return a + b;
  }
}

var add3 = add(3);

add3(4); returns 7

Wat jy kan sien, is dat wanneer jy 'n beroep te voeg met die parameter a (wat is 3), is dat waarde vervat in die sluiting van die teruggekeer funksie wat ons definieer om add3 wees. Op dié manier, wanneer ons add3 noem dit weet waar om die 'n waarde aan die toevoeging voer vind.

Kyle se antwoord is redelik goed. Ek dink die enigste bykomende verduideliking is dat die sluiting is basies 'n momentopname van die stapel op die punt dat die lambda funksie is geskep. Dan wanneer die funksie is weer uitgevoer die stapel herstel na daardie toestand voor die uitvoering van die funksie. So as Kyle noem, wat verborge waarde (count) is beskikbaar wanneer die lambda funksie voer.

Eerste van alles, in teenstelling met wat die meeste van die mense hier vertel, sluiting is nie 'n funksie!So, wat is dit?
Dit is'n stel van simbole gedefinieer in'n funksie se "omliggende konteks" (bekend as die omgewing wat maak dit'n GESLOTE uitdrukking (dit is, 'n uitdrukking wat in elke simbool is gedefinieer en het'n waarde, sodat dit geëvalueer kan word).

Byvoorbeeld, wanneer jy'n JavaScript-funksie:

function closed(x) {
  return x + 3;
}

dit is'n geslote uitdrukking omdat al die simbole wat in dit is gedefinieer in dit (hul betekenis is duidelik), sodat jy kan evalueer dit.In ander woorde, dit is self-vervat.

Maar as jy het'n funksie soos hierdie:

function open(x) {
  return x*y + 3;
}

dit is'n oop uitdrukking want daar is simbole in dit wat nie gedefinieer in dit.Naamlik, y.Wanneer jy kyk na hierdie funksie, kan ons nie vertel wat y is en wat beteken dit, ons weet nie die waarde daarvan, sodat ons nie kan evalueer hierdie uitdrukking.I. e.ons kan nie bel hierdie funksie totdat ons vertel wat y veronderstel is om te beteken in dit.Hierdie y is genoem'n gratis veranderlike.

Hierdie y smeek vir'n definisie, maar hierdie definisie is nie deel van die funksie – dit is gedefinieer iewers anders, in sy "omliggende konteks" (ook bekend as die omgewing).Ten minste dit is wat ons hoop vir :P

Byvoorbeeld, dit kan gedefinieer word wêreldwyd:

var y = 7;

function open(x) {
  return x*y + 3;
}

Of dit kan gedefinieer word in'n funksie wat vou dit:

var global = 2;

function wrapper(y) {
   var w = "unused";

   return function(x) {
     return x*y + 3;
   }

}

Die deel van die omgewing wat gee die gratis veranderlikes in'n uitdrukking hul betekenis, is die sluiting.Dit is genoem op hierdie manier, want dit blyk'n oop uitdrukking in'n gesluit een, deur die verskaffing van hierdie ontbreek definisies vir al sy gratis veranderlikes, sodat ons kan evalueer dit.

In die voorbeeld hierbo, die binneste funksie (wat ons het nie'n naam gee, want ons het nie dit nodig het) is'n oop uitdrukking omdat die veranderlike y in dit is gratis – sy definisie is buite die funksie, in die funksie wat vou dit.Die omgewing vir die anonieme funksie is die stel van veranderlikes:

{
  global: 2,
  w: "unused",
  y: [whatever has been passed to that wrapper function as its parameter `y`]
}

Nou, die sluiting is dat'n deel van hierdie omgewing wat sluit die binneste funksie deur die verskaffing van die definisies vir al sy gratis veranderlikes.In ons geval, die enigste vrye veranderlike in die binneste funksie was y, sodat die sluiting van daardie funksie is hierdie subset van sy omgewing:

{
  y: [whatever has been passed to that wrapper function as its parameter `y`]
}

Die ander twee simbole gedefinieer in die omgewing is nie deel van die sluiting van daardie funksie, omdat dit nie vereis dat hulle om te hardloop.Hulle is nie nodig om te naby dit.

Meer op die teorie agter dat hier:https://stackoverflow.com/a/36878651/434562

Dit is die moeite werd om daarop te let dat in die voorbeeld hierbo, die omslag funksie gee terug die binneste funksie as'n waarde.Die oomblik wat ons noem hierdie funksie kan wees remote in die tyd vanaf die oomblik wat die funksie is gedefinieer (of geskep het).In die besonder, sy wikkel funksie is nie meer loop, en die parameters wat op die oproep stapel is nie meer daar nie :P Dit maak'n probleem nie, want die binneste funksie behoeftes y om daar te wees wanneer dit genoem word!In ander woorde, dit vereis dat die veranderlikes van sy sluiting om een of ander manier oorleef die omslag funksie en daar wees wanneer dit nodig is.Daarom, die binneste funksie het om te maak'n foto van hierdie veranderlikes wat maak sy sluiting en stoor dit iewers veilig is vir latere gebruik.(Iewers buite die oproep stapel.)

En dit is die rede waarom mense dikwels verwar die term sluiting om daardie spesiale tipe van die funksie wat dit kan doen sulke foto's van die eksterne veranderlikes wat hulle gebruik, of die data struktuur wat gebruik word om te stoor hierdie veranderlikes vir later.Maar ek hoop jy verstaan nou dat hulle nie die sluiting self – hulle is net maniere om te implementeer sluitings in'n programmeertaal, of die taal meganismes wat toelaat dat die veranderlikes van die funksie se sluiting is om daar te wees wanneer dit nodig is.Daar is'n baie van die wanopvattings rondom sluitings wat (onnodig) maak hierdie onderwerp baie meer verwarrend en ingewikkeld dat dit eintlik is.

'n sluiting is 'n funksie wat die staat kan 'n verwysing in 'n ander funksie. Byvoorbeeld, in Python, hierdie gebruik die sluiting "innerlike":

def outer (a):
    b = "variable in outer()"
    def inner (c):
        print a, b, c
    return inner

# Now the return value from outer() can be saved for later
func = outer ("test")
func (1) # prints "test variable in outer() 1

Om jou te help fasiliteer begrip van sluitings dit kan nuttig wees om te kyk hoe hulle kan geïmplementeer word in'n prosedurele taal.Hierdie verduideliking sal volg'n eenvoudige implementering van sluitings in die Skema.

Om mee te begin, ek moet stel om die konsep van'n namespace.Wanneer jy tik'n bevel in'n Skema tolk, moet dit evalueer die verskillende simbole in die uitdrukking en kry hul waarde.Voorbeeld:

(define x 3)

(define y 4)

(+ x y) returns 7

Definieer die uitdrukkings die stoor van die waarde van die 3 in die plek vir x en die waarde 4 in die plek vir y.Dan wanneer ons noem (+ x y), die tolk lyk die waardes in die namespace en in staat is om die operasie uit te voer en terugkeer 7.

Egter, in die Skema daar is uitdrukkings wat u toelaat om tydelik ignoreer die waarde van'n simbool.Hier is'n voorbeeld:

(define x 3)

(define y 4)

(let ((x 5))
   (+ x y)) returns 9

x returns 3

Wat die laat navraag doen, is stel'n nuwe namespace met x as die waarde 5.Jy sal sien dat dit is nog steeds in staat om te sien dat y is 4, die maak van die bedrag teruggestuur te word 9.Jy kan ook sien dat sodra die uitdrukking het geëindig x is terug na die wese 3.In hierdie sin, x is tydelik gemaskerde deur die plaaslike waarde.

Prosedurele en objek-georiënteerde tale het'n soortgelyke konsep.Wanneer jy verklaar'n veranderlike in'n funksie wat het dieselfde naam as'n globale veranderlike jy kry die dieselfde effek.

Hoe sou ons die uitvoering van hierdie?'n eenvoudige manier is om met'n gekoppelde lys - die kop bevat die nuwe waarde en die stert bevat die ou namespace.Wanneer jy nodig het om te kyk op'n simbool, jy begin by die kop en werk jou pad af in die stert.

Nou kom ons slaan oor na die implementering van die eerste-klas funksies vir die oomblik.Meer of minder, 'n funksie is'n stel instruksies uit te voer wanneer die funksie genoem word wat kulmineer in die terugkeer waarde.Wanneer ons lees in'n funksie, ons kan stoor hierdie instruksies agter die skerms en hardloop hulle toe die funksie genoem.

(define x 3)

(define (plus-x y)
  (+ x y))

(let ((x 5))
  (plus-x 4)) returns ?

Ons definieer x 3 en plus-x om sy parameter, y, plus die waarde van x.Ten slotte het ons noem plus-x in'n omgewing waar x is gemaskerde deur'n nuwe x, hierdie een gewaardeer 5.As ons net die stoor van die operasie, (+ x y), vir die funksie plus-x, want ons is in die konteks van x 5 die resultaat teruggekeer sou word 9.Dit is wat genoem word dinamiese konsep.

Egter, Skema, Algemene Lisp, en baie ander tale het wat genoem leksikale omvangsbepaling - in bykomend tot die stoor van die operasie (+ x y) ons ook slaan die namespace op daardie spesifieke punt.Dat die manier, wanneer ons is op soek na die waardes wat ons kan sien dat x, in hierdie konteks, is regtig 3.Dit is'n sluiting.

(define x 3)

(define (plus-x y)
  (+ x y))

(let ((x 5))
  (plus-x 4)) returns 7

In die opsomming, kan ons gebruik om'n gekoppel lys te stoor die toestand van die namespace by die tyd van funksie definisie, wat ons toelaat om toegang te verkry veranderlikes van omringende bestekke, sowel as die verskaffing van ons die vermoë om plaaslik masker'n veranderlike sonder die invloed van die res van die program.

Hier is 'n tasbare voorbeeld van hoekom Closures skop gat ... Dit is reguit uit my Javascript kode. Laat my toe te lig.

Function.prototype.delay = function(ms /*[, arg...]*/) {
  var fn = this,
      args = Array.prototype.slice.call(arguments, 1);

  return window.setTimeout(function() {
      return fn.apply(fn, args);
  }, ms);
};

En hier is hoe jy dit sou gebruik:

var startPlayback = function(track) {
  Player.play(track);  
};
startPlayback(someTrack);

Nou dink jy wil die vertoning om te begin vertraag, soos byvoorbeeld 5 sekondes later na hierdie kode uit lopies. Wel, dit is maklik om met delay en dis sluiting:

startPlayback.delay(5000, someTrack);
// Keep going, do other things

As jy delay met 5000ms noem, die eerste brokkie loop, en winkels die afgelope in argumente in sy sluiting. Dan 5 sekondes later, toe die setTimeout terugbel gebeur, die sluiting hou nog steeds daardie veranderlikes, so dit die oorspronklike funksie met die oorspronklike parameters kan noem.
Dit is 'n tipe van currying, of funksie versiering.

Sonder sluitings, sal jy het om daardie veranderlikes staat een of ander manier in stand te hou buite die funksie, dus kode rommelstrooi buite die funksie met iets wat logies behoort binne dit. Die gebruik van sluitings kan aansienlik verbeter die gehalte en readiblity van jou kode.

tl;dr

'n sluiting is'n funksie en die omvang opgedra aan (of gebruik word as) 'n veranderlike.Dus, die naam sluiting:die omvang en die funksie is ingesluit en gebruik net soos enige ander entiteit.

In die diepte van die Wikipedia-styl verduideliking

Volgens Wikipedia, 'n sluiting is:

Tegnieke vir die implementering van lexically scoped naam bindend in tale met die eerste-klas funksies.

Wat beteken dit?Kom ons kyk na'n paar definisies.

Ek sal verduidelik sluitings en ander verwante definisies deur die gebruik van hierdie voorbeeld:

function startAt(x) {
    return function (y) {
        return x + y;
    }
}

var closure1 = startAt(1);
var closure2 = startAt(5);

console.log(closure1(3)); // 4 (x == 1, y == 3)
console.log(closure2(3)); // 8 (x == 5, y == 3)

Eerste-klas funksies

Basies beteken dit dat ons kan gebruik om funksies net soos enige ander entiteit.Ons kan verander hulle, slaag hulle as argumente, hulle terugkeer van funksies of wys hulle vir veranderlikes.Tegnies gesproke, hulle is eerste-klas burgers, vandaar die naam:eerste-klas funksies.

In die voorbeeld hierbo, startAt opbrengste van'n (anonieme) funksie wat die funksie kry opgedra aan closure1 en closure2.So as jy sien JavaScript behandel funksies net soos enige ander entiteite (eerste-klas burgers).

Naam bindend

Naam bindend is oor om uit te vind wat'n veranderlike data (identifikasie) verwysings.Die omvang is baie belangrik hier, want dit is die ding wat sal bepaal hoe'n bindende is opgelos.

In die voorbeeld hierbo:

  • In die binneste anonieme funksie se omvang, y is gebind om te 3.
  • In startAtse omvang, x is gebind om te 1 of 5 (afhangende van die sluiting).

Binne die anonieme funksie se omvang, x is nie gebonde aan enige waarde, so dit moet opgelos word in'n boonste (startAt's) omvang.

Leksikale omvangsbepaling

As Wikipedia sê, die omvang:

Is die streek van'n rekenaar program waar die bindende is geldig: waar die naam gebruik kan word om te verwys na die entiteit.

Daar is twee tegnieke:

  • Leksikale (statiese) bestekopname:'n veranderlike se definisie is opgelos deur te soek sy met blok-of funksie, dan as dit nie soek in die buitenste wat blok, en so aan.
  • Dinamiese bestekopname:Roeping funksie is deursoek, dan is die funksie wat genoem dat die roeping funksie, en so aan, vorder die oproep stapel.

Vir meer verduideliking, check uit hierdie vraag en neem'n blik op Wikipedia.

In die voorbeeld hierbo, kan ons sien dat JavaScript is lexically scoped, want wanneer x is opgelos, die binding word gesoek in die boonste (startAt's) omvang, wat gebaseer is op die bron-kode (die anonieme funksie wat lyk vir x word gedefinieer binne startAt) en nie gebaseer is op die oproep stapel, die manier (die omvang waar) die funksie genoem.

Wikkel (closuring) op

In ons voorbeeld, wanneer ons noem startAt, dit sal terugkeer'n (eerste-klas) funksie wat sal toegeken word aan closure1 en closure2 so'n sluiting is geskep, want die veranderlikes geslaag het 1 en 5 sal gered word binne startAtse omvang, wat sal ingesluit word met die terug anonieme funksie.Wanneer ons noem hierdie anonieme funksie via closure1 en closure2 met die dieselfde argument (3), die waarde van y sal gevind word onmiddellik (as dit is die parameter van daardie funksie), maar x is nie gebind in die omvang van die anonieme funksie, so die besluit steeds in die (lexically) boonste funksie omvang (die wat gered is in die sluiting) waar x is gevind in om gebind te wees om óf 1 of 5.Nou weet ons alles vir die opsomming so die gevolg kan teruggestuur word, dan gedruk.

Nou moet jy verstaan sluitings en hoe hulle optree, wat is'n fundamentele deel van JavaScript.

Currying

O ja, en jy het ook geleer wat currying is oor:jy gebruik funksies (sluitings) te slaag elke argument van'n operasie in plaas van die gebruik van een funksies met verskeie parameters.

Funksies wat nie 'n vrye veranderlikes genoem suiwer funksies.

Funksies wat een of meer gratis veranderlikes sluitings genoem.

var pure = function pure(x){
  return x 
  // only own environment is used
}

var foo = "bar"

var closure = function closure(){
  return foo 
  // foo is a free variable from the outer environment
}

src: https://leanpub.com/javascriptallongesix/read#leanpub-auto-if-functions-without-free-variables-are-pure-are-closures-impure

In 'n normale situasie, veranderlikes is gebind deur omvangsbepaling reël: Plaaslike veranderlikes werk slegs binne die gedefinieerde funksie. Die sluiting is 'n manier om te breek hierdie reël tydelik vir gerief.

def n_times(a_thing)
  return lambda{|n| a_thing * n}
end

in die bogenoemde kode, lambda(|n| a_thing * n} is die sluiting omdat a_thing verwys word deur die lambda ( 'n anonieme funksie skepper).

Nou, as jy die gevolglike anonieme funksie in 'n funksie veranderlike.

foo = n_times(4)

cat sal die normale bestekopname reël breek en begin met behulp van 4 intern.

foo.call(3)

terug 12.

In kort, funksie wyser is net 'n verwysing na 'n plek in die program kode basis (soos program toonbank). Terwyl Die afsluiting = Function wyser + stapel raamwerk .

.

Die afsluiting is 'n funksie in JavaScript waar 'n funksie het toegang tot sy eie omvang veranderlikes, toegang tot die buitenste funksie veranderlikes en toegang tot die globale veranderlikes.

Die afsluiting het toegang tot sy buitenste funksie omvang, selfs nadat die buitenste funksie teruggekeer het. Dit beteken 'n sluiting kan onthou en toegang veranderlikes en argumente van sy buitenste funksie, selfs nadat die funksie klaar.

Die binneste funksie kan toegang tot die veranderlikes gedefinieer in sy eie omvang, omvang die buitenste funksie se en die globale omvang. En die buitenste funksie kan toegang tot die veranderlike gedefinieer in sy eie omvang en die globale omvang.

******************
Example of Closure
******************

var globalValue = 5;

function functOuter() 
{
    var outerFunctionValue = 10;

    //Inner function has access to the outer function value
    //and the global variables
    function functInner() 
    {
        var innerFunctionValue = 5;
        alert(globalValue+outerFunctionValue + innerFunctionValue);
    }
    functInner();
}
functOuter();

Uitgawe sal wees 20 wat som van sy binneste funksie eie veranderlike, buitenste funksie veranderlike en globale veranderlike waarde.

Hier is nog 'n werklike lewe voorbeeld, en met behulp van 'n script taal gewild in speletjies - Lua. Ek nodig het om 'n bietjie te verander die manier waarop 'n biblioteek funksie gewerk om 'n probleem te vermy met stdin nie beskikbaar is nie.

local old_dofile = dofile

function dofile( filename )
  if filename == nil then
    error( 'Can not use default of stdin.' )
  end

  old_dofile( filename )
end

Die waarde van old_dofile verdwyn wanneer hierdie blok van die kode afwerkings dis omvang (want dit is plaaslik), maar die waarde is ingesluit in 'n sluiting, so die nuwe geherdefinieer dofile funksie kan toegang, of eerder 'n kopie gestoor saam met die funksie as 'n "upvalue.

Uit Lua.org:

Wanneer'n funksie is geskryf ingesluit in'n ander funksie, dit het volle toegang tot die plaaslike veranderlikes van die omringende funksie;hierdie funksie is genoem leksikale bestekopname.Hoewel dit mag klink voor die hand liggend, dit is nie.Leksikale bestekopname, plus die eerste-klas funksies, is'n kragtige konsep in'n programmeertaal, maar'n paar tale ondersteun dat die konsep.

As jy uit die Java wêreld, jy kan 'n sluiting vergelyk met 'n lid funksie van 'n klas. Kyk na hierdie voorbeeld

var f=function(){
  var a=7;
  var g=function(){
    return a;
  }
  return g;
}

Die funksie g is 'n sluiting: g sluit a in So g kan vergelyk word met 'n lid funksie, a kan vergelyk word met 'n klas veld, en die funksie f met 'n klas

..

Closures Wanneer ons 'n funksie gedefinieer binne 'n ander funksie, die binneste funksie het toegang tot die verklaarde veranderlikes in die buitenste funksie. Sluitings is die beste verduidelik met voorbeelde. In Listing 2-18, kan jy sien dat die binneste funksie het toegang tot 'n veranderlike (variableInOuterFunction) van die buitenste ruimte. Die veranderlikes in die buitenste funksie is afgeskakel deur (of gebind in) die binneste funksie. Vandaar die term sluiting. Die konsep op sigself is eenvoudig genoeg en redelik intuïtief.

Listing 2-18:
    function outerFunction(arg) {
     var variableInOuterFunction = arg;

     function bar() {
             console.log(variableInOuterFunction); // Access a variable from the outer scope
     }
     // Call the local function to demonstrate that it has access to arg
     bar(); 
    }
    outerFunction('hello closure!'); // logs hello closure!

bron: http://index-of.es/Varios/Basarat%20Ali%20Syed%20 (auth.) -Beginning% 20Node.js-Apress% 20 (2014) .pdf

Neem asseblief'n blik hieronder kode te verstaan sluiting in meer diep:

        for(var i=0; i< 5; i++){            
            setTimeout(function(){
                console.log(i);
            }, 1000);                        
        }

Hier is wat sal uitvoer? 0,1,2,3,4 nie wat sal wees 5,5,5,5,5 as gevolg van die sluiting

So, hoe sal dit op te los?Antwoord hieronder:

       for(var i=0; i< 5; i++){
           (function(j){     //using IIFE           
                setTimeout(function(){
                               console.log(j);
                           },1000);
            })(i);          
        }

Laat my eenvoudig verduidelik, wanneer'n funksie geskep het niks gebeur totdat dit so genoem vir die lus in die 1-kode bekend as 5 keer, maar nie genoem onmiddellik so wanneer dit genoem word ek.e na 1 sekonde en ook dit is asynchrone so voor die for-lus klaar en die stoor van die waarde 5 in die var ek en uiteindelik uit te voer setTimeout funksie vyf keer en druk 5,5,5,5,5

Hier is hoe dit op te los met behulp van IIFE ek.e Onmiddellike Oproep Funksie Uitdrukking

       (function(j){  //i is passed here           
            setTimeout(function(){
                           console.log(j);
                       },1000);
        })(i);  //look here it called immediate that is store i=0 for 1st loop, i=1 for 2nd loop, and so on and print 0,1,2,3,4

Vir meer, asseblief verstaan uitvoering konteks te verstaan sluiting.

  • Daar is een oplossing om dit op te los met behulp laat (ES6 funksie), maar onder die enjinkap bogenoemde funksie is gewerk

     for(let i=0; i< 5; i++){           
         setTimeout(function(){
                        console.log(i);
                    },1000);                        
     }
    
    Output: 0,1,2,3,4
    

=> Meer verduideliking:

In die geheue, wanneer lus voer prentjie maak soos hieronder:

Lus 1)

     setTimeout(function(){
                    console.log(i);
                },1000);  

Lus 2)

     setTimeout(function(){
                    console.log(i);
                },1000); 

Lus 3)

     setTimeout(function(){
                    console.log(i);
                },1000); 

Lus 4)

     setTimeout(function(){
                    console.log(i);
                },1000); 

Lus 5)

     setTimeout(function(){
                    console.log(i);
                },1000);  

Hier het ek is nie uitgevoer nie en dan na die volledige lus, var ek gestoor waarde 5 in die geheue, maar dit is die omvang is altyd sigbaar in dit se kinders funksie sodat wanneer die funksie uit te voer binne setTimeout uit die vyf keer is dit afdrukke 5,5,5,5,5

so om op te los hierdie gebruik IIFE soos verduidelik hierbo.

Currying: Dit laat jou toe om 'n funksie gedeeltelik evalueer deur net verby in 'n subset van sy argumente. Oorweeg hierdie:

function multiply (x, y) {
  return x * y;
}

const double = multiply.bind(null, 2);

const eight = double(4);

eight == 8;

Die afsluiting: 'n sluiting is niks meer as toegang tot 'n veranderlike buite bestek n funksie se. Dit is belangrik om te onthou dat 'n funksie binne 'n funksie of 'n sub-funksie is nie 'n sluiting. Sluitings is altyd gebruik wanneer nodig om toegang te verkry tot die veranderlikes buite die funksie omvang.

function apple(x){
   function google(y,z) {
    console.log(x*y);
   }
   google(7,2);
}

apple(3);

// the answer here will be 21

Die afsluiting is baie maklik. Ons kan dit oorweeg soos volg: Sluiting = funksie + sy leksikale omgewing

Oorweeg die volgende funksie:

function init() {
    var name = “Mozilla”;
}

Wat sal die sluiting in die bogenoemde geval wees? Funksie init () en veranderlikes in sy leksikale omgewing dws naam. Die afsluiting = init () + naam

Oorweeg 'n ander funksie:

function init() {
    var name = “Mozilla”;
    function displayName(){
        alert(name);
}
displayName();
}

Wat sal die sluitings hier? Binneste funksie kan toegang veranderlikes van die buitenste funksie. Display () toegang tot die in die ouer funksie verklaar veranderlike naam, init (). Dit sal egter dieselfde plaaslike veranderlikes in DISPLAYNAME () gebruik word as hulle bestaan.

Die afsluiting 1: init funksie + (naam veranderlike + DISPLAYNAME () funksie) -> leksikale omvang

Die afsluiting 2: Display funksie + (naam veranderlike) -> leksikale omvang

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top