Heim  >  Artikel  >  Web-Frontend  >  JavaScript-Grundlagen (6) Funktionsausdruck-Closure_Javascript-Kenntnisse

JavaScript-Grundlagen (6) Funktionsausdruck-Closure_Javascript-Kenntnisse

WBOY
WBOYOriginal
2016-05-16 15:26:22927Durchsuche

Tatsächlich ist der Hauptgrund, warum js Funktionsabschlüsse unterstützt, dass js Funktionen benötigt, um Daten speichern zu können. Die hier gespeicherten Daten bestehen darin, dass nach Beendigung der Funktion nur die Werte der Variablen in der Funktion gespeichert werden. Warum js in der Lage sein muss, Daten innerhalb einer Funktion zu speichern, ist, dass js eine funktionale Sprache ist. Das Speichern von Daten innerhalb von Funktionen ist ein Markenzeichen funktionaler Sprachen.

Sehen Sie sich die drei zuvor vorgestellten Methoden zum Definieren von Funktionen an

functiosu(numnumreturnunum//Syntaxdefinition der Funktionsdeklaration
vasufunction(numnum)returnunum}//Funktionsausdrucksdefinition
vasuneFunction("num""num""returnunum")//Functio-Konstruktor

Bevor wir Abschlüsse analysieren, werfen wir zunächst einen Blick auf die häufigsten Fehler beim Definieren und Aufrufen von Funktionen.

Beispiel 1:

sayHi(); //错误:函数还不存在
var sayHi = function () {
  alert("test");
};

Beispiel 2:

if (true) {
  function sayHi() {
    alert("1");
  }
} else {
  function sayHi() {
    alert("2");
  }
}
sayHi();//打印结果并不是我们想要的

Beispiel 3:

var fun1 = function fun2() {
  alert("test");
}
fun2();//错误:函数还不存在

In Beispiel 1 können wir die Funktion nicht aufrufen, bevor wir sie mithilfe der deklarativen Funktionssyntax definiert haben. Lösung:

1. Wenn Sie einen Funktionsausdruck verwenden, um eine Funktion zu definieren, muss diese aufgerufen werden, nachdem der Ausdruck definiert wurde.

var sayHi = function () {
  alert("test");
};
sayHi()

2. Verwenden Sie Funktionsdeklarationen. (Hier fördert die Browser-Engine Funktionsdeklarationen und liest die Funktionsdeklaration, bevor der gesamte Code ausgeführt wird)

sayHi(); 
function sayHi () {
  alert("test");
};

In Beispiel 2 sollte unser erwartetes Ergebnis darin bestehen, 1 zu drucken, aber das tatsächliche Ergebnis ist das Drucken von 2.

if (true) {
  function sayHi() {
   alert("1");
  }
  } else {
  function sayHi() {
   alert("2");
  }
}
sayHi();//打印结果并不是我们想要的

Warum passiert das? Aufgrund der Funktionsdeklarationsförderung beurteilt der Browser die if-Bedingung während der Voranalyse nicht und überschreibt die erste direkt, wenn er die zweite Funktionsdefinition analysiert.

Lösung:

var sayHi;
if (true) {
  sayHi = function () {
   alert("1");
  }
  } else {
  sayHi = function () {
   alert("2");
  }
}
sayHi();

In Beispiel 3 haben wir festgestellt, dass wir nur fun1() zum Aufrufen verwenden können, nicht jedoch fun2().

Nach meinem eigenen Verständnis kenne ich den wahren Grund nicht. Keine Informationen gefunden.

Weil 1: function fun3() { }; var fun3 = function fun3() { } ist, wie in der Abbildung gezeigt:

Sie können also nur fun1() zum Aufrufen verwenden, nicht jedoch fun2().

Eigentlich habe ich hier noch Fragen? Wenn es jemand weiß, lasst es mich bitte wissen.

Da fun2 nicht von außen aufgerufen werden kann, warum kann es dann von innerhalb der Funktion aufgerufen werden? Obwohl ich fun1 im Debugger immer noch nicht hinbekomme.

Okay, lass uns mit den drei oben genannten Fragen aufwärmen. Machen wir weiter mit dem heutigen Thema „Schließungen“.

1. Was ist Schließung?

Definition: Es handelt sich um eine Funktion, die Zugriff auf Variablen im Gültigkeitsbereich einer anderen Funktion hat

Beginnen wir mit einer Beispielfunktion:

Beispiel 1:

function fun() {
  var a = "张三";
}
fun();//在我们执行完后,变量a就被标记为销毁了

Beispiel 2:

function fun() {
  var a = "张三";
  return function () {
    alert("test");
  }
}
var f = fun();//同样,在我们执行完后,变量a就被标记为销毁了

Beispiel 3:

function fun() {
  var a = "张三";
  return function () {
    alert(a);
  }
}
var f = fun();//【现在情况发生变化了,如果a被销毁,显然f被调用的话就不能访问到变量a的值了】
f();//【然后变量a的值正常的被访问到了】
//这就是闭包,当函数A 返回的函数B 里面使用到了函数A的变量,那么函数B就使用了闭包。
示例:
function fun() {
  var a = "张三";
  return function () {
   alert(a);
  }
}
var f = fun();//【现在情况发生变化了,如果a被销毁,显然f被调用的话就不能访问到变量a的值了】
f();//【然后变量a的值正常的被访问到了】

Offensichtlich erhöht der Missbrauch von Schließungen die Speichernutzung. Versuchen Sie daher, keine Schließungen zu verwenden, es sei denn, es liegen besondere Umstände vor. Denken Sie bei Verwendung daran, manuell eine Nullreferenz festzulegen, damit der Speicher recycelt werden kann f = null ;

Abbildung: (Studenten, die die Scope-Kette nicht verstehen, lesen bitte zuerst den vorherigen Artikel Scope und Scope-Kette)

2. Was ist eine anonyme Funktion? (Ich erkläre nur das Konzept)

Zum Beispiel: (das heißt eine Funktion ohne Namen)

Über das seltsame Phänomen, wenn der Rückgabewert der Funktion im Objekt eine anonyme Funktion ist

Bevor Sie es erklären, machen Sie bitte zunächst einen klaren Kopf und lassen Sie sich beim Lesen nicht noch mehr verwirren. Wenn Sie verwirrt sind, ignorieren Sie einfach Folgendes.

var name1 = "张三";
var obj = {
  name1: "李四",      
  fun2: function () {
    alert(this.name1);
  },
  fun3: function () {
    return function () {
      alert(this.name1);
    }
  }
}

obj.fun2();//Das Druckergebnis „李思“ ist wie erwartet.
obj.fun3()();//Da es sich hier um eine Funktion handelt, müssen wir ein Paar () hinzufügen, um sie aufzurufen. Das gedruckte Ergebnis ist „Zhang San“, was unerwartet ist.
//Es ist wirklich verwirrend. Was bedeutet das für die Gesamtsituation?
Wir haben zuvor gesagt: „Welches Objekt auch immer auf die Methode klickt, das ist das Objekt“, dann gibt unser obj.fun3()() „Zhang San“ aus, was bedeutet, dass dies den globalen Bereich ausführt.

Vielleicht verstehen wir den Grund, wenn wir uns das folgende Beispiel ansehen.

var name1 = "张三";
var obj = {
  name1: "李四",      
  fun2: function () {
    alert(this.name1);
  },
  fun3: function () {
    return function () {
      alert(this.name1);
    }
  }
}    
//obj.fun3()();
var obj2 = {};
obj2.name1 = "test";
obj2.fun = obj.fun3();
obj2.fun();//打印结果"test",再次证明了“哪个对象点出来的方法,this就是哪个对象”.
var name1 = "张三";
var obj = {
  name1: "李四",
  fun2: function () {
   alert(this.name1);
  },
  fun3: function () {
    return function () {
     alert(this.name1);
    }
  }
}
//obj.fun3()();
var obj2 = {};
obj2.name1 = "test";
obj2.fun = obj.fun3();
obj2.fun();//打印结果"test",再次证明了“哪个对象点出来的方法,this就是哪个对象”.

Lassen Sie uns obj.fun3()() zerlegen. Zuerst gibt obj.fun3() eine anonyme Funktion an den Fensterbereich zurück und ruft diese dann auf, um auf das Fenster zu zeigen. (Ich habe das Gefühl, dass die Erklärung etwas erzwungen ist und ich weiß nicht, ob sie richtig ist oder nicht. So verstehe ich es im Moment)

Ursache der Verschlussbildung: Gedächtnisfreisetzungsproblem

Im Allgemeinen wird beim Ausführen der Funktion das lokal aktive Objekt zerstört und nur der globale Bereich im Speicher gespeichert. Bei Schließungen ist die Situation jedoch anders.

Das aktive Objekt des Abschlusses wird weiterhin im Speicher gespeichert. Im obigen Beispiel gehört die Variable i nach der Rückkehr des Funktionsaufrufs zum aktiven Objekt, was bedeutet, dass sein Stapelbereich noch nicht freigegeben wurde Sie rufen c() auf. Wenn die von der i-Variablen gespeicherte Bereichskette global von b()->a()-> reicht, sucht sie nach der Bereichsvariable i-Deklaration und findet dann var i=1; ; das Ergebnis innerhalb des Abschlusses und schließlich Der Ausgabewert ist 2;

Das Obige ist der Funktionsausdrucksabschluss in JavaScript-Grundlagen Teil 6, den der Herausgeber mit Ihnen geteilt hat. Ich hoffe, er gefällt Ihnen.

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn