Detaillierte Einführung in JavaScript-Funktionen

1. Funktionseinführung

Eine Funktion kapselt den Code, der eine bestimmte Funktion implementiert. Wenn wir eine bestimmte Funktion implementieren müssen, können wir die Funktion direkt aufrufen, um sie zu implementieren. Es ist nicht erforderlich, jedes Mal eine Menge Code zu schreiben, um eine Wiederverwendung des Codes zu erreichen.

Funktionen:
1. Kapseln Sie Funktionen und verbessern Sie die Wiederverwendung von Code.
2. Vorlagen (Konstruktoren), die zum Erstellen von Objekten verwendet werden

Funktionen sind eigentlich Objekte. Jede Funktion ist eine Instanz des Funktionstyps und verfügt über Eigenschaften und Methoden wie andere Referenztypen. Da Funktionen Objekte sind, ist der Funktionsname tatsächlich ein Zeiger auf das Funktionsobjekt und wird keiner bestimmten Funktion zugeordnet. Funktionsbindung.

2. Funktionsdeklaration

Grammatik:

function 函数名(形参列表){
    
    
    //函数体
}

Wir können es auch als Funktionsausdruck schreiben:

var 函数名 = function(形参列表){
    
    
    //函数体
}

Beispiel:

// 函数声明
function sum(a,b){
    
    
  return a + b
}
//函数声明之后,需要调用才能执行
// 函数调用:函数名(实参)
console.log(sum(1,2))  //3

Als Funktionsausdruck geschrieben:

// 函数声明
var sum = function(a,b){
    
    
  return a + b
}
// 函数调用:函数名(实参)
console.log(sum(1,2)) //3

Funktionsdeklarationsförderung
Die Funktionsdeklaration ähnelt den von var deklarierten Variablen, und es gibt auch eine Deklarationsförderung.

sum(1,2) //在此处调用函数不会报错,因为存在函数声明提升
function sum(a,b){
    
    
  return a + b
}

Hinweis: Wenn Sie eine Funktion mithilfe eines Funktionsausdrucks deklarieren, können Sie den Funktionsaufruf nicht vor der Funktionsdeklaration schreiben, da bei der Variablenzuweisung keine Heraufstufung erfolgt.

3. Interne Eigenschaften der Funktion

Auf funktionsinterne Eigenschaften kann nur innerhalb der Funktion zugegriffen werden

Argumente

arguments ist ein Array-ähnliches Objekt, das alle an die Funktion übergebenen Parameter enthält. Der Hauptzweck von Argumenten besteht darin, Funktionsparameter zu speichern.

function foo(){
    
    
  console.log(arguments) // [Arguments] { '0': 1, '1': 2, '2': 3, '3': 4 }
  console.log(arguments[1]) // 2
}
// 当传递的实参个数超过形参的个数的时候不会报错,所有的实参都会保存在arguments里
foo(1,2,3,4) 

Hinweis: Argumente werden in Argumenten gespeichert, nicht in formalen Parametern.

function foo(a,b = 2,c = 3){
    
    
  console.log(arguments) // [Arguments] { '0': 1 }
  console.log(b) //2
  console.log(c) //3
}
//只传了一个实参,那么arguments中就只有一个值
foo(1) 
Aufgerufenes Attribut

Das Argumentobjekt verfügt über eine Eigenschaft namens callee, die ein Zeiger auf die Funktion ist, die das Argumentobjekt besitzt.

arguments.calleeEs ist eigentlich der Funktionsname.

// 递归求n的阶乘
function factorial(n) {
    
    
  if (n == 1) {
    
    
    return 1
  }
  return arguments.callee(n - 1) * n //arguments.callee 相当于函数名factorial
}
console.log(factorial(10));
Längenattribut

Die Längeneigenschaft des Argumentobjekts gibt die Anzahl der tatsächlichen Argumente zurück.

function foo(){
    
    
  console.log(arguments.length) //5
}
foo(1,2,3,4,5) 

4. Bezüglich dieses Hinweises

Dies: Kontextobjekt der Ausführungsumgebung. Auf wen es verweist, hängt davon ab, wann und von wem es aufgerufen wird.

  • In einer Methode stellt dies das Objekt dar, zu dem die Methode gehört.
  • Bei alleiniger Verwendung stellt dies das globale Objekt dar.
  • In einer Funktion stellt dies das globale Objekt dar.
  • In einem Ereignis stellt dies das Element dar, das das Ereignis empfängt.
  • Bei der expliziten Funktionsbindung können wir den Sinn davon selbst entscheiden.

1. Dies in der Methode

Bei Objektmethoden zeigt dies auf das Objekt, das die Methode aufruft, in der es sich befindet. Das heißt, wer auch immer diese Methode aufruft, dies zeigt auf.

var person = {
    
    
  name:'叶子yes',
  sayName: function () {
    
    
    console.log(this.name); 
  }
}
//person对象调用了该方法,因此this指向person
person.sayName() // '叶子yes'
var name = 'hello'
    var person = {
    
    
      name: '叶子yes',
      sayName: function () {
    
    
        console.log(this.name);
      }
    }
var a = person.sayName
//这里是全局对象调用了sayName方法,因此this指向全局对象window,结果为'hello'
//注意:在node环境下执行时,结果为undefined
a()

2. Verwenden Sie dies allein

Wenn dies alleine verwendet wird, zeigt es auf das globale Objekt.

  • Im Browser ist window das globale Objekt
  • Im Knoten zeigt es auf ein {}

In der Browserumgebung:
Fügen Sie hier eine Bildbeschreibung ein
In der Knotenumgebung:

console.log(this) // {}

3. Verwenden Sie dies in Funktionen

In einer Funktion ist der Eigentümer der Funktion standardmäßig daran gebunden.

  • Im Browser zeigt es auf window
  • Im Knoten zeigt es auf das globale Objekt

In der Browserumgebung:
Fügen Sie hier eine Bildbeschreibung ein
In der Knotenumgebung:

function foo(){
    
    
  return this
}
console.log(foo())

Ausgabeergebnis:
Fügen Sie hier eine Bildbeschreibung ein

4. Dies in der Veranstaltung

In einem HTML-Ereignishandler verweist dies auf das HTML-Element, das das Ereignis empfangen hat:

<button onclick="this.style.display='none'"> 点我后我就消失了 </button> //this指向button

5. Funktionsbindung anzeigen

In JavaScript sind Funktionen auch Objekte, und Objekte haben Methoden. Apply und Call sind Methoden von Funktionsobjekten. Diese beiden Methoden sind äußerst leistungsfähig. Sie ermöglichen das Wechseln des Kontexts, in dem die Funktion ausgeführt wird, also des daran gebundenen Objekts. (Diese beiden Methoden werden später besprochen)

Wenn wir im folgenden Beispiel die Methode person1.sayName mit person2 als Parameter aufrufen, verweist diese auf person2, obwohl es sich um die Methode von person1 handelt:

var person1 = {
    
    
  name: 'zhangsan',
  sayName: function () {
    
    
    console.log(this.name);
  }
}
var person2 = {
    
    
  name:'叶子yes'
}
//this指向person2
person1.sayName.call(person2) //叶子yes

5. Führen Sie sofort die Funktion IIFE aus

IIFE: Sofort aufgerufener Funktionsausdruck, dh ein sofort aufgerufener Funktionsausdruck, dh die Funktion wird sofort aufgerufen, wenn die Funktion deklariert wird.

Funktion
1. Die Einstellungsfunktion wird nur einmal ausgeführt, nachdem die Seite geladen wurde.
2. Wickeln Sie die Variablen in der Einstellungsfunktion in den lokalen Bereich ein, damit sie nicht in globale Variablen gelangen.

Schreibmethode:

(function(形参){
    
    
	函数体内容
})(实参);

oder:

(function(形参){
    
    
	函数体内容
}(实参));

Beispiel:

(function (a) {
    
    
  console.log(123 + a); //124
})(1)
(function (a) {
    
    
  console.log(123 + a); //124
}(1))

Wenn wir eine normale Funktion und eine Funktion zur sofortigen Ausführung schreiben, müssen wir darauf achten, sie durch Semikolons zu trennen, sonst analysiert der js-Compiler sie in einer Anweisung und meldet einen Fehler:

// 普通函数
function foo() {
    
    
  console.log(123);
}
foo();
// 如果后面跟的是立即执行函数,前面的结束语句必须要加分号
// 立即执行函数
(function (a) {
    
    
  console.log(123 + a);
})(123)

Verwendung:
1. Eine sofort ausgeführte Funktion kann wie jede andere Funktion auch einen Wert zurückgeben und anderen Variablen zugewiesen werden:

var sum = (function (a,b) {
    
    
  return a + b;
}(1,2))
console.log(sum); //3

2. Sie können es vor der Funktion zur sofortigen Ausführung hinzufügen! , + usw., um eine Typkonvertierung für den Rückgabewert durchzuführen:

//1、返回布尔值
!function(形参){
    
    
	return true
}(实参)

//2、返回数字类型的值
+function(形参){
    
    
	return 123
}(实参)

//3、对于数字返回的是相反数,非数字返回NaN
-function(形参){
    
    
	return 123
}(实参)

//4、对于数字返回的是相反数减1,非数字返回-1
~function(形参){
    
    
	return 123
}(实参)

//5、返回undefined
void function(形参){
    
    
	函数体内容
}(实参)

3. Fragen im Vorstellungsgespräch

//下面代码输出结果是什么
for (var i = 0; i < 6; i++) {
    
    
  function output() {
    
    
    console.log(i); 
  }
}
output() //输出结果是6,因为函数执行时,for循环已经结束,函数体中最终存的i值是6

Was sollen wir tun, wenn wir 0,1,2,3,4,5 ausgeben möchten? Zu diesem Zeitpunkt können wir die Funktion zur sofortigen Ausführung verwenden:

for (var i = 0; i < 6; i++) {
    
    
  (function (j) {
    
    
    console.log(j); //0,1,2,3,4,5
  })(i)
}
/*
因为 JS 中调用函数传递参数都是值传递 ,所以当立即执行函数执行时,
首先会把参数 i 的值复制一份,然后再创建函数作用域来执行函数,
循环6次就会创建6个作用域,所以每个输出访问的都是不同作用域的 i 的值 。
*/

6. Geltungsbereich

In ES5: (In ES5 gibt es keinen Bereich auf Blockebene)

Funktionsumfang : In einer JavaScript-Funktion deklarierte Variablen werden zu lokalen Variablen der Funktion.
Auf innerhalb einer Funktion deklarierte Variablen kann außerhalb der Funktion nicht zugegriffen werden.

Globaler Geltungsbereich : Außerhalb der Funktion deklarierte Variablen werden zu globalen Variablen.
Auf außerhalb der Funktion deklarierte Variablen kann innerhalb der Funktion zugegriffen werden.
​ Wenn Funktionen verschachtelt sind, bilden zu diesem Zeitpunkt die Variablen der inneren Funktion und der äußeren Funktion einen Abschluss.

// 全局作用域定义的变量,函数作用域里是可以获取到的
var v1 = 10
v3 = 30
function foo() {
    
    
  // 函数局部作用域里面定义的变量,外界是获取不到的
  var v2 = 20
  console.log(v1, v2, v3); //10 20 30
}
foo()
console.log(v2); //ReferenceError: v2 is not defined

Fügen Sie hier eine Bildbeschreibung ein
Die größte Verwendung des Bereichs besteht darin, Variablen zu isolieren. Variablen mit demselben Namen in verschiedenen Bereichen treten nicht in Konflikt.

Scope-Kette

Lernen wir zunächst die freien Variablen kennen :
Im folgenden Code console.log(a)müssen wir die Variable a abrufen, aber a ist im aktuellen Bereich nicht definiert (vergleiche b). Im aktuellen Bereich sind keine Variablen definiert, die zu freien Variablen werden . So erhalten Sie den Wert der freien Variablen: Sie müssen zum übergeordneten Bereich gehen, in dem die Funktion erstellt wurde. Wenn nicht, suchen Sie immer nach dem oberen Vorgängerelement (dies ist der sogenannte „statische Bereich“. Der statische Bereich bezieht sich auf der Umfang der Funktion. Dieser wird bei der Definition der Funktion festgelegt)

var a = 100
function fn() {
    
    
    var b = 200
    console.log(a) // 这里的a 就是一个自由变量  // 100
    console.log(b)
}
fn()

Scope-Kette:

Die freie Variable wird entlang des Bereichs bis zum übergeordneten Bereich durchsucht. Wenn der übergeordnete Bereich nicht gefunden wird, wird er Schicht für Schicht durchsucht, bis der globale Bereich gefunden, aber immer noch nicht gefunden wird, und dann aufgegeben. Diese Schicht-für-Schicht-Beziehung ist die Bereichskette.

var a = 100
function F1() {
    
    
  var b = 200
  function F2() {
    
    
    var c = 300
    console.log(a) // 自由变量,顺作用域链向父作用域找 //100
    console.log(b) // 自由变量,顺作用域链向父作用域找 //200
    console.log(c) // 本作用域的变量  //300
  }
  F2()
}
F1()

Fügen Sie hier eine Bildbeschreibung ein

7. Funktionsaufruf

Nachdem die Funktion deklariert wurde, wird sie nicht direkt ausgeführt. Sie muss aufgerufen werden, bevor sie ausgeführt werden kann.
Die Art und Weise, eine Funktion aufzurufen, ist nicht auf die Ausführung von () beschränkt.

So rufen Sie die Funktion auf:

  • Funktionsname (aktuelle Parameterliste);
  • Funktionsname.call (Ausführungsumgebungsobjekt, tatsächliche Parameterliste);
  • Funktionsname.apply (Ausführungsumgebungsobjekt, tatsächliches Parameterlistenarray);
  • Funktionsname.bind (Ausführungsumgebungsobjekt) (aktuelle Parameterliste);

Im Folgenden werden die Methoden call, apply und bind vorgestellt:

1. Aufruf (Ausführungsumgebungsobjekt, tatsächliche Parameterliste);

Die Aufrufmethode wird verwendet, um den Punkt zu ändern. Der erste Parameter gibt den Punkt an, und die folgenden Parameter geben die tatsächlich übergebenen Parameter an, die null, eins oder mehr sein können.

var obj = {
    
    
  name: '叶子yes',
  sayName: function (a,b) {
    
    
    console.log(this.name); // 叶子yes
    console.log(a,b); // 1,2
  }
}
var b = obj.sayName;
b.call(obj,1,2); // this 指向 obj
2. Apply (Ausführungsumgebungsobjekt, tatsächliches Parameterlistenarray);

Die Apply-Methode ist grundsätzlich mit der Call-Methode identisch und wird auch zum Ändern des Zeigers dieser Methode verwendet. Der Unterschied besteht darin, dass Apply bei der Übergabe tatsächlicher Parameter ein Array verwendet.

var obj = {
    
    
  name: '叶子yes',
  sayName: function (a,b) {
    
    
    console.log(this.name); // 叶子yes
    console.log(a,b); // 1,2
  }
}
var b = obj.sayName;
b.apply(obj,[1,2]); // this 指向 obj,实参列表要写成数组的形式

Hinweis: Wenn der erste Parameter von call und apply null ist, verweist dies auf das globale Objekt in der Knotenumgebung und das Fensterobjekt in HTML.

var obj = {
    
    
  name: '叶子yes',
  sayName: function (a,b) {
    
    
    console.log(this); // window 或者 global
  }
}
var b = obj.sayName;
b.apply(null);
3. bind (Ausführungsumgebungsobjekt) (aktuelle Parameterliste);

Bind wird ebenfalls verwendet, um den Sinn zu ändern, aber bind(执行环境对象)es gibt eine Funktion zurück, die noch nicht ausgeführt wurde. Sie müssen () verwenden, um die Funktion auszuführen.

var obj = {
    
    
  name: '叶子yes',
  sayName: function (a,b) {
    
    
    console.log(this.name); // 叶子yes
    console.log(a,b); // 1,2
  }
}
var b = obj.sayName;
var c = b.bind(obj) //返回函数,此时还没有执行,需要再使用()来执行
console.log(c) //[Function: bound sayName]
c(1,2) //执行函数

Zusammenfassung: Sowohl Aufruf als auch Anwendung ändern dies im Kontext und führen die Funktion sofort aus. Mit der Bindungsmethode kann die entsprechende Funktion jederzeit aufgerufen werden, und Parameter können während der Ausführung hinzugefügt werden. Das ist ihr Unterschied.

8. Rückruffunktion

Rückruf bedeutet Rückruf. Die Hauptfunktion wird im Voraus abgeschlossen und die übergebene Funktion wird später aufgerufen.

Die Rolle der Rückruffunktion: Die Rückruffunktion wird im Allgemeinen für zeitaufwändige Vorgänge verwendet: Da die Hauptfunktion nicht auf den Abschluss der Rückruffunktion warten muss, kann sie weiterhin ihren eigenen Code ausführen. Zum Beispiel eine Ajax-Anfrage, z. B. die Verarbeitung von Dateien usw.

Lassen Sie uns einfach die Callback-Funktion simulieren:

//定义主函数,回调函数作为参数
function A(callback) {
    
    
  callback();
  console.log('我是主函数');
}
//定义回调函数
function B() {
    
    
  // 模仿延时操作
  setTimeout(() => {
    
    
    console.log('我是回调函数');
  }, 3000);
}
//调用主函数,将函数B传进去
A(B);
输出结果为:
我是主函数
我是回调函数

Geben Sie zuerst „Ich bin die Hauptfunktion“ und dann nach 3 Sekunden „Ich bin die Rückruffunktion“ aus.

9. Schließung

1. Was ist ein Abschluss?
Einfach ausgedrückt bezieht sich ein Abschluss auf eine Funktion, die das Recht hat, auf Variablen im Gültigkeitsbereich einer anderen Funktion zuzugreifen.

Verschlüsse sind eine besondere Art von Objekten . Es besteht aus zwei Teilen: einer Funktion und der Umgebung, in der die Funktion erstellt wird. Die Umgebung besteht aus allen lokalen Variablen, die zum Zeitpunkt der Erstellung des Abschlusses im Gültigkeitsbereich waren.

2. Bedingungen für die Abschlussbildung

Es gibt drei notwendige Bedingungen für die Generierung von Abschlüssen:
1. Funktionsverschachtelte Funktionen
2. Interne Funktionen beziehen sich auf Daten (Eigenschaften, Funktionen) in externen Funktionen
3. Parameter und Variablen werden nicht recycelt

Dadurch entsteht ein Funktionsraum, der nicht zerstört wird.

Der Abschluss im folgenden Beispiel ist ein Abschluss:

function func() {
    
    
  var a = 1, b = 2;

  function closure() {
    
    
    return a + b;
  }
  return closure;
}
console.log(func()()); // 3

Die Bereichskette eines Abschlusses enthält seinen eigenen Bereich sowie den Bereich seiner enthaltenden Funktion und den globalen Bereich.

In der Javascript-Sprache können nur Unterfunktionen innerhalb einer Funktion lokale Variablen lesen, sodass Abschlüsse einfach als „innerhalb einer Funktion definierte Funktionen“ verstanden werden können.

Im Wesentlichen ist der Abschluss also eine Brücke, die das Innere der Funktion mit der Außenseite der Funktion verbindet.

3. Die Rolle des Abschlusses

Verschlüsse können an vielen Stellen eingesetzt werden. Seine größten Verwendungszwecke sind zwei: Zum einen werden die Variablen innerhalb der Funktion gelesen, zum anderen werden die Werte dieser Variablen im Speicher gehalten.

function f1() {
    
    
  var n = 999;
  nAdd = function () {
    
     
  	n += 1 
  }
  function f2() {
    
    
    console.log(n);
  }
  return f2;
}
var result = f1();
result(); // 999
nAdd();
result(); // 1000

In diesem Code ist das Ergebnis tatsächlich die Abschlussfunktion f2. Es wurde zweimal ausgeführt, beim ersten Mal war der Wert 999, beim zweiten Mal war der Wert 1000. Dies beweist, dass die lokale Variable n in der Funktion f1 immer im Speicher gespeichert ist und nach dem Aufruf von f1 nicht automatisch gelöscht wird.

Warum ist das so? Der Grund dafür ist, dass f1 die übergeordnete Funktion von f2 ist und f2 einer globalen Variablen zugewiesen ist, wodurch f2 immer im Speicher bleibt und die Existenz von f2 von f1 abhängt, sodass f1 immer im Speicher ist und nicht gelöscht wird Nach Abschluss des Anrufs wird es vom Garbage-Collection-Mechanismus recycelt.

Eine weitere bemerkenswerte Sache in diesem Code ist die Zeile „nAdd=function(){n+=1}“. Erstens wird das Schlüsselwort var nicht vor nAdd verwendet, sodass nAdd eine globale Variable und keine lokale Variable ist. Zweitens ist der Wert von nAdd eine anonyme Funktion, und die anonyme Funktion selbst ist auch ein Abschluss, sodass nAdd einem Setter entspricht, der lokale Variablen innerhalb der Funktion außerhalb der Funktion bearbeiten kann.

4. Zu beachtende Punkte bei der Verwendung von Verschlüssen

(1) Da Schließungen dazu führen, dass die Variablen in der Funktion im Speicher gespeichert werden, was viel Speicher verbraucht, können Schließungen nicht missbraucht werden, da es sonst zu Leistungsproblemen auf der Webseite und möglicherweise zu Speicherverlusten im IE kommt. Dies ist das Problem des IE. BUG. Die Lösung besteht darin, alle nicht verwendeten lokalen Variablen zu löschen, bevor die Funktion beendet wird.

(2) Der Abschluss ändert den Wert der Variablen innerhalb der übergeordneten Funktion außerhalb der übergeordneten Funktion. Wenn Sie daher die übergeordnete Funktion als Objekt, den Abschluss als öffentliche Methode und die internen Variablen als privaten Wert verwenden, müssen Sie darauf achten, den Wert der Variablen innerhalb der übergeordneten Funktion nicht zu ändern. Die Bereiche mehrerer untergeordneter Funktionen verweisen gleichzeitig auf die übergeordnete Funktion und werden vollständig gemeinsam genutzt. Wenn also das Variablenobjekt des übergeordneten Elements geändert wird, sind alle untergeordneten Funktionen betroffen.

Supongo que te gusta

Origin blog.csdn.net/lq313131/article/details/126291274
Recomendado
Clasificación