Heim > Artikel > Web-Frontend > 10 schwierige Punkte, die in JavaScript beherrscht werden müssen (muss gelesen werden)
Möglicherweise kennen Sie die 10 JavaScript-Schwierigkeiten noch nicht, keine Sorge, dieser Artikel listet sie einzeln auf und kann sie einzeln überwinden. Interessierte Freunde können sich auf
beziehen, um dieses Blog-JavaScript zu verstehen Entwickler werden kein Pech haben...
1. Führen Sie die Funktion sofort aus
Führen Sie die Funktion sofort aus, d. h. den sofort aufgerufenen Funktionsausdruck (IIFE). Der Name bedeutet, dass die Funktion sofort ausgeführt wird, wenn sie erstellt wird. Es bindet keine Ereignisse und muss nicht auf asynchrone Vorgänge warten:
(function() { // 代码 // ... })();
function(){…} ist eine anonyme Funktion, und ein sie umgebendes Klammerpaar wandelt sie in einen Ausdruck um. gefolgt von Das folgende Klammerpaar ruft diese Funktion auf. Das sofortige Ausführen einer Funktion kann auch als sofortiges Aufrufen einer anonymen Funktion verstanden werden. Das häufigste Anwendungsszenario für die sofortige Ausführung einer Funktion besteht darin, den Gültigkeitsbereich der Variablen var auf Ihre Funktion zu beschränken, um Namenskonflikte zu vermeiden.
2. Abschluss
Beim Abschluss kann die innere Funktion nach der Rückkehr der äußeren Funktion weiterhin auf die Variablen der äußeren Funktion zugreifen.
function f1() { var N = 0; // N是f1函数的局部变量 function f2() // f2是f1函数的内部函数,是闭包 { N += 1; // 内部函数f2中使用了外部函数f1中的变量N console.log(N); } return f2; } var result = f1(); result(); // 输出1 result(); // 输出2 result(); // 输出3
Im Code wird die externe Funktion f1 nur einmal ausgeführt, die Variable N wird auf 0 gesetzt und die interne Funktion f2 wird der Variablen result zugewiesen. Da die externe Funktion f1 ausgeführt wurde, sollte ihre interne Variable N im Speicher gelöscht werden. Dies ist jedoch nicht der Fall: Bei jedem Aufruf von result stellen wir fest, dass die Variable N im Speicher war und sich ansammelt. Warum? Das ist die Magie der Verschlüsse!
3. Verwenden Sie Abschlüsse, um private Variablen zu definieren
Normalerweise verwenden JavaScript-Entwickler einen Unterstrich als Präfix für private Variablen. Tatsächlich kann auf diese Variablen jedoch weiterhin zugegriffen und sie geändert werden, es handelt sich also nicht um wirklich private Variablen. Zu diesem Zeitpunkt können Sie Abschlüsse verwenden, um echte private Variablen zu definieren:
function Product() { var name; this.setName = function(value) { name = value; }; this.getName = function() { return name; }; } var p = new Product(); p.setName("Fundebug"); console.log(p.name); // 输出undefined console.log(p.getName()); // 输出Fundebug
Im Code ist das Namensattribut von Objekt p ein privates Attribut, auf das nicht direkt mit p.name zugegriffen werden kann.
4. Prototyp
Jeder JavaScript-Konstruktor verfügt über ein Prototypattribut, das zum Festlegen der Eigenschaften und Methoden verwendet wird, die alle Instanzobjekte gemeinsam nutzen müssen. Die Prototypeigenschaft kann nicht aufgezählt werden. JavaScript unterstützt nur die Vererbung von Eigenschaften und Methoden über das Prototyp-Attribut.
function Rectangle(x, y) { this._length = x; this._breadth = y; } Rectangle.prototype.getDimensions = function() { return { length: this._length, breadth: this._breadth }; }; var x = new Rectangle(3, 4); var y = new Rectangle(4, 3); console.log(x.getDimensions()); // { length: 3, breadth: 4 } console.log(y.getDimensions()); // { length: 4, breadth: 3 }
Im Code sind x und y beide Objektinstanzen, die vom Konstruktor „Rectangle“ erstellt wurden, und sie erben die getDimensions-Methode über den Prototyp.
5. Modularität
JavaScript ist keine modulare Programmiersprache, zumindest nicht bis ES6 implementiert ist. Für eine komplexe Webanwendung ist jedoch die modulare Programmierung die grundlegendste Voraussetzung. Derzeit können Sie Funktionen zur sofortigen Ausführung verwenden, um Modularität zu erreichen, ebenso wie viele JS-Bibliotheken wie jQuery und unser Fundebug auf diese Weise implementiert werden.
var module = (function() { var N = 5; function print(x) { console.log("The result is: " + x); } function add(a) { var x = a + N; print(x); } return { description: "This is description", add: add }; })(); console.log(module.description); // 输出"this is description" module.add(5); // 输出“The result is: 10”
Die sogenannte Modularisierung dient dazu, die Zugänglichkeit von Attributen und Methoden innerhalb des Moduls je nach Bedarf, also privat oder öffentlich, zu steuern. Im Code ist Modul ein unabhängiges Modul, N ist seine private Eigenschaft, print ist seine private Methode, Beschreibung ist seine öffentliche Eigenschaft und add ist seine öffentliche Methode.
6. Variablen-Heben
JavaScript verschiebt alle Variablen- und Funktionsdeklarationen an den Anfang seines Gültigkeitsbereichs, was als Variablen-Heben (Heben) bezeichnet wird. Das heißt, egal wo Sie Variablen und Funktionen deklarieren, der Interpreter verschiebt sie an den Anfang des Gültigkeitsbereichs. Wir können also zuerst Variablen und Funktionen verwenden und diese dann deklarieren.
Es werden jedoch nur Variablendeklarationen gefördert, während Variablenzuweisungen nicht gefördert werden. Wenn Sie dies nicht verstehen, tritt manchmal ein Fehler auf:
console.log(y); // 输出undefined y = 2; // 初始化y
Der obige Code entspricht dem folgenden Code:
var y; // 声明y console.log(y); // 输出undefined y = 2; // 初始化y
Um Fehler zu vermeiden, sollten Entwickler Variablen und Funktionen werden am Anfang des Bereichs deklariert.
7. Currying
Currying, also Currying, kann Funktionen flexibler machen. Wir können es aufrufen, indem wir mehrere Parameter gleichzeitig übergeben; wir können es auch aufrufen, indem wir nur einen Teil der Parameter übergeben und es eine Funktion zurückgeben lassen, um die verbleibenden Parameter zu verarbeiten.
var add = function(x) { return function(y) { return x + y; }; }; console.log(add(1)(1)); // 输出2 var add1 = add(1); console.log(add1(1)); // 输出2 var add10 = add(10); console.log(add10(1)); // 输出11
Im Code können wir zwei Einsen gleichzeitig als Parameter add(1)(1) übergeben, oder wir können einen Parameter übergeben und dann die Funktionen add1 und add10 erhalten sehr flexibel einsetzbar.
8. Apply-, Call- und Bind-Methoden
JavaScript-Entwickler müssen die Unterschiede zwischen Apply-, Call- und Bind-Methoden verstehen. Gemeinsam ist ihnen, dass es sich beim ersten Parameter um den Kontext handelt, von dem die Funktion bei der Ausführung abhängt.
Von den dreien ist die Call-Methode die einfachste. Sie entspricht dem Aufruf einer Funktion durch Angabe dieses Werts:
var user = { name: "Rahul Mhatre", whatIsYourName: function() { console.log(this.name); } }; user.whatIsYourName(); // 输出"Rahul Mhatre", var user2 = { name: "Neha Sampat" }; user.whatIsYourName.call(user2); // 输出"Neha Sampat"
Die Apply-Methode ähnelt der Call-Methode. Der einzige Unterschied zwischen den beiden besteht darin, dass die Apply-Methode ein Array zur Angabe von Parametern verwendet, während jeder Parameter der Call-Methode einzeln angegeben werden muss:
apply(thisArg, [argsArray]) call(thisArg, arg1, arg2, …) var user = { greet: "Hello!", greetUser: function(userName) { console.log(this.greet + " " + userName); } }; var greet1 = { greet: "Hola" }; user.greetUser.call(greet1, "Rahul"); // 输出"Hola Rahul" user.greetUser.apply(greet1, ["Rahul"]); // 输出"Hola Rahul"
Mit der Bind-Methode können Sie diesen Wert binden zur Funktion hinzufügen und sie dann als neue Funktion verwenden Die Berechnungsergebnisse werden in den Speicher geschrieben, sodass der Eingabewert beim nächsten Mal nur noch aus dem Speicher gelesen werden muss.
var user = { greet: "Hello!", greetUser: function(userName) { console.log(this.greet + " " + userName); } }; var greetHola = user.greetUser.bind({greet: "Hola"}); var greetBonjour = user.greetUser.bind({greet: "Bonjour"}); greetHola("Rahul") // 输出"Hola Rahul" greetBonjour("Rahul") // 输出"Bonjour Rahul"
Im Code muss bei der zweiten Berechnung von Fibonacci (100) das Ergebnis nur direkt aus dem Speicher gelesen werden.
10. Funktionsüberlastung所谓函数重载(method overloading),就是函数名称一样,但是输入输出不一样。或者说,允许某个函数有各种不同输入,根据不同的输入,返回不同的结果。凭直觉,函数重载可以通过if…else或者switch实现,这就不去管它了。jQuery之父John Resig提出了一个非常巧(bian)妙(tai)的方法,利用了闭包。
从效果上来说,people对象的find方法允许3种不同的输入: 0个参数时,返回所有人名;1个参数时,根据firstName查找人名并返回;2个参数时,根据完整的名称查找人名并返回。
难点在于,people.find只能绑定一个函数,那它为何可以处理3种不同的输入呢?它不可能同时绑定3个函数find0,find1与find2啊!这里的关键在于old属性。
由addMethod函数的调用顺序可知,people.find最终绑定的是find2函数。然而,在绑定find2时,old为find1;同理,绑定find1时,old为find0。3个函数find0,find1与find2就这样通过闭包链接起来了。
根据addMethod的逻辑,当f.length与arguments.length不匹配时,就会去调用old,直到匹配为止。
function addMethod(object, name, f) { var old = object[name]; object[name] = function() { // f.length为函数定义时的参数个数 // arguments.length为函数调用时的参数个数 if (f.length === arguments.length) { return f.apply(this, arguments); } else if (typeof old === "function") { return old.apply(this, arguments); } }; } // 不传参数时,返回所有name function find0() { return this.names; } // 传一个参数时,返回firstName匹配的name function find1(firstName) { var result = []; for (var i = 0; i < this.names.length; i++) { if (this.names[i].indexOf(firstName) === 0) { result.push(this.names[i]); } } return result; } // 传两个参数时,返回firstName和lastName都匹配的name function find2(firstName, lastName) { var result = []; for (var i = 0; i < this.names.length; i++) { if (this.names[i] === (firstName + " " + lastName)) { result.push(this.names[i]); } } return result; } var people = { names: ["Dean Edwards", "Alex Russell", "Dean Tom"] }; addMethod(people, "find", find0); addMethod(people, "find", find1); addMethod(people, "find", find2); console.log(people.find()); // 输出["Dean Edwards", "Alex Russell", "Dean Tom"] console.log(people.find("Dean")); // 输出["Dean Edwards", "Dean Tom"] console.log(people.find("Dean", "Edwards")); // 输出["Dean Edwards"]
Das obige ist der detaillierte Inhalt von10 schwierige Punkte, die in JavaScript beherrscht werden müssen (muss gelesen werden). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!