354 Stimmen

Was ist eine praktische Anwendung für eine Schließung in JavaScript?

Ich bin Versuch Ich tue mich schwer damit, JavaScript-Schließungen zu verstehen.

Ich verstehe, dass durch die Rückgabe einer inneren Funktion, wird es Zugriff auf jede Variable in seiner unmittelbaren Eltern definiert haben.

Wo wäre dies für mich von Nutzen? Vielleicht habe ich es noch nicht ganz begriffen. Die meisten der Beispiele, die ich online gesehen habe bieten keinen realen Code, sondern nur vage Beispiele.

Kann mir jemand zeigen, wie ein Verschluss in der Praxis eingesetzt wird?

Ist dies zum Beispiel eine?

var warnUser = function (msg) {
    var calledCount = 0;
    return function() {
       calledCount++;
       alert(msg + '\nYou have been warned ' + calledCount + ' times.');
    };
};

var warnForTamper = warnUser('You can not tamper with our HTML.');
warnForTamper();
warnForTamper();

5voto

Abhilash KK Punkte 438

Hier habe ich ein einfaches Beispiel für das Verschlusskonzept, das wir für unsere E-Commerce-Website oder viele andere auch verwenden können.

Ich füge meinen JSFiddle-Link mit dem Beispiel hinzu. Es enthält eine kleine Produktliste mit drei Artikeln und einen Warenkorbzähler.

JSFiddle

// Counter closure implemented function;
var CartCouter = function(){
  var counter = 0;

  function changeCounter(val){
      counter += val
  }

  return {
      increment: function(){
        changeCounter(1);
    },
    decrement: function(){
      changeCounter(-1);
    },
    value: function(){
      return counter;
    }
  }
}

var cartCount = CartCouter();

function updateCart() {
  document.getElementById('cartcount').innerHTML = cartCount.value();
}

var productlist = document.getElementsByClassName('item');
for(var i = 0; i< productlist.length; i++){
  productlist[i].addEventListener('click', function(){
    if(this.className.indexOf('selected') < 0){
      this.className += " selected";
      cartCount.increment();
      updateCart();
    }
    else{
      this.className = this.className.replace("selected", "");
      cartCount.decrement();
      updateCart();
    }
  })
}

.productslist{
  padding: 10px;
}
ul li{
  display: inline-block;
  padding: 5px;
  border: 1px solid #DDD;
  text-align: center;
  width: 25%;
  cursor: pointer;
}
.selected{
  background-color: #7CFEF0;
  color: #333;
}
.cartdiv{
  position: relative;
  float: right;
  padding: 5px;
  box-sizing: border-box;
  border: 1px solid #F1F1F1;
}

<div>
    <h3>
        Practical use of a JavaScript closure concept/private variable.
    </h3>

    <div class="cartdiv">
        <span id="cartcount">0</span>
    </div>

    <div class="productslist">
        <ul>
            <li class="item">Product 1</li>
            <li class="item">Product 2</li>
            <li class="item">Product 3</li>
        </ul>
    </div>
</div>

4voto

Sunny S.M Punkte 5198

Verwendung von Verschlüssen:

Closures sind eine der mächtigsten Funktionen von JavaScript. JavaScript ermöglicht die Verschachtelung von Funktionen und gewährt der inneren Funktion vollen Zugriff auf alle Variablen und Funktionen, die innerhalb der äußeren Funktion definiert sind (und auf alle anderen Variablen und Funktionen, auf die die äußere Funktion Zugriff hat). Die äußere Funktion hat jedoch keinen Zugriff auf die Variablen und Funktionen, die innerhalb der inneren Funktion definiert sind.

Dies bietet eine Art Sicherheit für die Variablen der inneren Funktion. Da die innere Funktion Zugriff auf den Geltungsbereich der äußeren Funktion hat, leben die in der äußeren Funktion definierten Variablen und Funktionen länger als die äußere Funktion selbst, falls es der inneren Funktion gelingt, über die Lebensdauer der äußeren Funktion hinaus zu überleben. Eine Closure wird erstellt, wenn die innere Funktion auf irgendeine Weise für einen Bereich außerhalb der äußeren Funktion verfügbar gemacht wird.

Beispiel:

<script>
var createPet = function(name) {
  var sex;

  return {
    setName: function(newName) {
      name = newName;
    },

    getName: function() {
      return name;
    },

    getSex: function() {
      return sex;
    },

    setSex: function(newSex) {
      if(typeof newSex == "string" && (newSex.toLowerCase() == "male" || newSex.toLowerCase() == "female")) {
        sex = newSex;
      }
    }
  }
}

var pet = createPet("Vivie");
console.log(pet.getName());                  // Vivie

console.log(pet.setName("Oliver"));   
console.log(pet.setSex("male"));
console.log(pet.getSex());                   // male
console.log(pet.getName());                  // Oliver
</script>

Im obigen Code ist die Namensvariable der äußeren Funktion für die inneren Funktionen zugänglich, und es gibt keine andere Möglichkeit, auf die inneren Variablen zuzugreifen als über die inneren Funktionen. Die inneren Variablen der inneren Funktion dienen als sichere Speicher für die inneren Funktionen. Sie enthalten "beständige", aber sichere Daten, mit denen die inneren Funktionen arbeiten können. Die Funktionen müssen nicht einmal einer Variablen zugewiesen werden oder einen Namen haben. lesen aquí für Details.

2voto

Sundar Gautam Punkte 305

Es gibt verschiedene Anwendungsfälle von Closures. hier werde ich die wichtigste Verwendung des Closure-Konzepts erklären.

  • Closure kann verwendet werden, um private Methoden und Variablen zu erstellen, genau wie in einer objektorientierten Sprache wie Java, C++ und so weiter. Sobald Sie private Methoden und Variablen implementiert haben, sind Ihre Variablen, die innerhalb einer Funktion definiert sind, für das Fensterobjekt nicht mehr zugänglich. Dies hilft beim Verstecken von Daten und bei der Datensicherheit.

    const privateClass = () => { let name = "sundar"; function setName(changeName) { name = changeName; } function getName() { return name; } return { setName: setName, getName: getName, }; };

    let javaLikeObject = privateClass(); \ similar to new Class() in OOPS.

    console.log(javaLikeObject.getName()); \this will give sundar javaLikeObject.setName("suresh"); console.log(javaLikeObject.getName()); \this will give suresh

  • Ein weiteres Beispiel aus dem wirklichen Leben für einen Abschluss:

Erstellen Sie index.html:

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Program with Javascript</title>
  </head>
  <body>
    <p id="first"></p>
    <p id="second"></p>
    <button onclick="applyingConcepts()">Click</button>
    <script src="./index.js"></script>
  </body>
</html>

2) In index.js:

  let count = 0;
  return () => {
    document.getElementById("first").innerHTML = count++;
  };
})();
  • Wenn Sie in diesem Beispiel auf eine Schaltfläche klicken, wird Ihr Zählerstand auf p#id aktualisiert. Hinweis: Sie fragen sich vielleicht, was an diesem Code so besonders ist. Wenn Sie ihn sich ansehen, werden Sie feststellen, dass Sie den Wert von count nicht über das Fensterobjekt ändern können. Das bedeutet, dass Sie die private Variable count deklariert haben, um zu verhindern, dass Ihre Zustände durch den Client verdorben werden.

2voto

Mandeep Kaur Punkte 49

Erläuterung der praktischen Verwendung eines Abschlusses in JavaScript

Wenn wir eine Funktion innerhalb einer anderen Funktion erstellen, schaffen wir eine Schließung. Closures sind sehr leistungsfähig, da sie die Daten ihrer äußeren Funktionen lesen und manipulieren können. Jedes Mal, wenn eine Funktion aufgerufen wird, wird ein neuer Bereich für diesen Aufruf erstellt. Die innerhalb der Funktion deklarierten lokalen Variablen gehören zu diesem Bereich und können nur von dieser Funktion aus aufgerufen werden. Wenn die Funktion ihre Ausführung beendet hat, wird der Bereich normalerweise zerstört.

Ein einfaches Beispiel für eine solche Funktion ist die folgende:

function buildName(name) {
    const greeting = "Hello, " + name;
    return greeting;
}

Im obigen Beispiel deklariert die Funktion buildName() eine lokale Variable greeting und gibt sie zurück. Jeder Funktionsaufruf erzeugt einen neuen Bereich mit einer neuen lokalen Variablen. Nachdem die Funktion ausgeführt wurde, gibt es keine Möglichkeit mehr, auf diesen Bereich zu verweisen, also wird er in den Müll geworfen.

Aber was ist, wenn wir eine Verbindung zu diesem Bereich haben?

Schauen wir uns die nächste Funktion an:

function buildName(name) {
    const greeting = "Hello, " + name + " Welcome ";
    const sayName = function() {
        console.log(greeting);
    };
    return sayName;
}

const sayMyName = buildName("Mandeep");
sayMyName();  // Hello, Mandeep Welcome

Die Funktion sayName() aus diesem Beispiel ist eine Schließung. Die Funktion sayName() hat ihren eigenen lokalen Bereich (mit der Variable welcome) und hat auch Zugriff auf den Bereich der äußeren (umschließenden) Funktion. In diesem Fall ist das die Variable greeting aus buildName().

Nachdem die Ausführung von buildName abgeschlossen ist, wird der Bereich in diesem Fall nicht zerstört. Die Funktion sayMyName() hat immer noch Zugriff auf ihn, so dass er nicht gelöscht wird. Es gibt jedoch keine andere Möglichkeit, auf Daten aus dem äußeren Bereich zuzugreifen, außer der Schließung. Die Closure dient als Gateway zwischen dem globalen Kontext und dem äußeren Bereich.

2voto

Darren Crabb Punkte 548

Dieser Thread hat mir sehr geholfen, ein besseres Verständnis für die Funktionsweise von Verschlüssen zu erlangen.

Ich habe inzwischen selbst ein wenig experimentiert und bin dabei auf diesen recht einfachen Code gestoßen, der vielleicht auch anderen helfen kann, zu erkennen, wie Closures praktisch eingesetzt werden können und wie man Closures auf verschiedenen Ebenen einsetzen kann, um Variablen zu pflegen, die statischen und/oder globalen Variablen ähneln, ohne Gefahr zu laufen, dass sie überschrieben oder mit globalen Variablen verwechselt werden.

Damit werden die Schaltflächenklicks verfolgt, und zwar sowohl auf lokaler Ebene für jede einzelne Schaltfläche als auch auf globaler Ebene, wobei jeder Schaltflächenklick gezählt wird und zu einer einzigen Zahl beiträgt. Beachten Sie, dass ich dafür keine globalen Variablen verwendet habe. Das ist ja gerade der Sinn der Übung - einen Handler zu haben, der auf jede Schaltfläche angewendet werden kann, die auch zu etwas Globalem beiträgt.

Bitte, liebe Experten, lassen Sie mich wissen, ob ich hier etwas falsch gemacht habe! Ich bin selbst noch dabei, diese Dinge zu lernen.

<!doctype html>
<html>

<head>
    <meta charset="utf-8">
    <title>Closures on button presses</title>

    <script type="text/javascript">

        window.addEventListener("load" , function () {
            /*
                Grab the function from the first closure,
                and assign to a temporary variable
                this will set the totalButtonCount variable
                that is used to count the total of all button clicks
            */
            var buttonHandler = buttonsCount();

            /*
                Using the result from the first closure (a function is returned)
                assign and run the sub closure that carries the
                individual variable for button count and assign to the click handlers
            */
            document.getElementById("button1").addEventListener("click" , buttonHandler() );
            document.getElementById("button2").addEventListener("click" , buttonHandler() );
            document.getElementById("button3").addEventListener("click" , buttonHandler() );

            // Now that buttonHandler has served its purpose it can be deleted if needs be
            buttonHandler = null;
        });

        function buttonsCount() {
            /*
                First closure level
                - totalButtonCount acts as a sort of global counter to count any button presses
            */
            var totalButtonCount = 0;

            return  function () {
                // Second closure level
                var myButtonCount = 0;

                return function (event) {
                    // Actual function that is called on the button click
                    event.preventDefault();
                    /*
                       Increment the button counts.
                       myButtonCount only exists in the scope that is
                       applied to each event handler and therefore acts
                       to count each button individually, whereas because
                       of the first closure totalButtonCount exists at
                       the scope just outside, it maintains a sort
                       of static or global variable state
                    */

                    totalButtonCount++;
                    myButtonCount++;

                    /*
                        Do something with the values ... fairly pointless
                        but it shows that each button contributes to both
                        its own variable and the outer variable in the
                        first closure
                    */
                    console.log("Total button clicks: "+totalButtonCount);
                    console.log("This button count: "+myButtonCount);
                }
            }
        }
    </script>
</head>

<body>
    <a href="#" id="button1">Button 1</a>
    <a href="#" id="button2">Button 2</a>
    <a href="#" id="button3">Button 3</a>
</body>

</html>

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X