Vorwort
Dies, der Konstruktor und der Prototyp in JavaScript sind alles alltägliche Probleme, und es ist wichtig, ihre Bedeutung genau zu verstehen. Lassen Sie uns es noch einmal Revue passieren lassen, die Vergangenheit Revue passieren lassen und das Neue lernen!
dieses
Dies stellt das aktuelle Objekt dar, wenn es im globalen Bereich verwendet wird. Wenn es in einer Funktion verwendet wird, basiert es auf dem Objekt, auf das sich diese Funktion bezieht zur Laufzeit. Wir können auch die beiden globalen Methoden apply und call verwenden, um den spezifischen Zeiger davon in der Funktion zu ändern.
Sehen wir uns zunächst ein Beispiel für die Verwendung im globalen Bereich an:
console.log(this === window); // true console.log(window.alert === this.alert); // true console.log(this.parseInt("021", 10)); // 10
Dies in der Funktion wird zur Laufzeit bestimmt, nicht wenn die Funktion definiert wird, wie folgt:
// 定义一个全局函数 function foo() { console.log(this.fruit); } // 定义一个全局变量,等价于window.fruit = "apple"; var fruit = "apple"; // 此时函数foo中this指向window对象 // 这种调用方式和window.foo();是完全等价的 foo(); // "apple" // 自定义一个对象,并将此对象的属性foo指向全局函数foo var pack = { fruit: "orange", foo: foo }; // 此时函数foo中this指向window.pack对象 pack.foo(); // "orange"
Mit den globalen Funktionen apply und call kann der Zeiger hierfür in der Funktion wie folgt geändert werden:
// 定义一个全局函数 function foo() { console.log(this.fruit); } // 定义一个全局变量 var fruit = "apple"; // 自定义一个对象 var pack = { fruit: "orange" }; // 等价于window.foo(); foo.apply(window); // "apple" // 此时foo中的this === pack foo.apply(pack); // "orange"
Hinweis: Die Apply- und Call-Funktionen haben die gleiche Funktion. Der einzige Unterschied besteht darin, dass die Parameterdefinitionen der beiden Funktionen unterschiedlich sind.
Da Funktionen in JavaScript auch Objekte sind, können wir die folgenden interessanten Beispiele sehen:
// 定义一个全局函数 function foo() { if (this === window) { console.log("this is window."); } } // 函数foo也是对象,所以可以定义foo的属性boo为一个函数 foo.boo = function() { if (this === foo) { console.log("this is foo."); } else if (this === window) { console.log("this is window."); } }; // 等价于window.foo(); foo(); // this is window. // 可以看到函数中this的指向调用函数的对象 foo.boo(); // this is foo. // 使用apply改变函数中this的指向 foo.boo.apply(window); // this is window.
Prototyp
Prototype ist im Wesentlichen ein JavaScript-Objekt.
Und jede Funktion verfügt über ein Standard-Prototypattribut. Wenn diese Funktion im Zusammenhang mit der Erstellung eines benutzerdefinierten Objekts verwendet wird, nennen wir diese Funktion einen Konstruktor. Zum Beispiel die folgende einfache Szene:
// 构造函数 function Person(name) { this.name = name; } // 定义Person的原型,原型中的属性可以被自定义对象引用 Person.prototype = { getName: function() { return this.name; } } var hao= new Person("haorooms"); console.log(hao.getName()); // "haorooms"
Als Analogie betrachten wir die Datentypen in JavaScript – Zeichenfolge, Zahl, Array, Objekt, Datum usw.
Wir haben Grund zu der Annahme, dass diese Typen als Konstruktoren in JavaScript implementiert sind, wie zum Beispiel:
// 定义数组的构造函数,作为JavaScript的一种预定义类型 function Array() { // ... } // 初始化数组的实例 var arr1 = new Array(1, 56, 34, 12); // 但是,我们更倾向于如下的语法定义: var arr2 = [1, 56, 34, 12];
Gleichzeitig sollten auch viele Methoden zum Bearbeiten von Arrays (z. B. Concat, Join, Push) im Prototypattribut definiert werden. Tatsächlich haben alle intrinsischen JavaScript-Datentypen ein schreibgeschütztes Prototypattribut (das ist verständlich: Wenn Sie das Prototypattribut dieser Typen ändern, verschwinden die vordefinierten Methoden), aber wir können ihm eine eigene Erweiterungsmethode hinzufügen.
// 向JavaScript固有类型Array扩展一个获取最小值的方法 Array.prototype.min = function() { var min = this[0]; for (var i = 1; i < this.length; i++) { if (this[i] < min) { min = this[i]; } } return min; }; // 在任意Array的实例上调用min方法 console.log([1, 56, 34, 12].min()); // 1
Hinweis: Nach dem Hinzufügen einer Erweiterungsmethode zum Array-Prototyp wird diese Erweiterungsmethode auch ausgeschleift, wenn for-in zum Durchschleifen des Arrays verwendet wird. Der folgende Code veranschaulicht dies (vorausgesetzt, die min-Methode wurde auf den Array-Prototyp erweitert):
var arr = [1, 56, 34, 12]; var total = 0; for (var i in arr) { total += parseInt(arr[i], 10); } console.log(total); // NaN
Die Lösung ist auch ganz einfach:
var arr = [1, 56, 34, 12]; var total = 0; for (var i in arr) { if (arr.hasOwnProperty(i)) { total += parseInt(arr[i], 10); } } console.log(total); // 103
Konstrukteur
Konstruktor zeigt immer auf den Konstruktor, der das aktuelle Objekt erstellt hat. Zum Beispiel das folgende Beispiel:
// 等价于 var foo = new Array(1, 56, 34, 12); var arr = [1, 56, 34, 12]; console.log(arr.constructor === Array); // true // 等价于 var foo = new Function(); var Foo = function() { }; console.log(Foo.constructor === Function); // true // 由构造函数实例化一个obj对象 var obj = new Foo(); console.log(obj.constructor === Foo); // true // 将上面两段代码合起来,就得到下面的结论 console.log(obj.constructor.constructor === Function); // true
Aber wenn der Konstrukteur auf den Prototyp trifft, passiert etwas Interessantes. Wir wissen, dass jede Funktion über einen Standardattributprototyp verfügt und der Konstruktor dieses Prototyps standardmäßig auf diese Funktion verweist. Wie im folgenden Beispiel gezeigt:
function Person(name) { this.name = name; }; Person.prototype.getName = function() { return this.name; }; var p = new Person("haorooms"); console.log(p.constructor === Person); // true console.log(Person.prototype.constructor === Person); // true // 将上两行代码合并就得到如下结果 console.log(p.constructor.prototype.constructor === Person); // true
Als wir den Prototyp der Funktion neu definierten (Hinweis: Der Unterschied zum obigen Beispiel besteht darin, dass es sich nicht um eine Änderung, sondern um eine Überschreibung handelt), war das Verhalten des Konstruktors etwas seltsam, wie im folgenden Beispiel gezeigt:
function Person(name) { this.name = name; }; Person.prototype = { getName: function() { return this.name; } }; var p = new Person("haorooms"); console.log(p.constructor === Person); // false console.log(Person.prototype.constructor === Person); // false console.log(p.constructor.prototype.constructor === Person); // false
Warum? Es stellt sich heraus, dass das Überschreiben von Person.prototype dem Ausführen der folgenden Codeoperation entspricht:
Person.prototype = new Object({ getName: function() { return this.name; } });
Der Konstruktor zeigt immer auf den Konstruktor, der sich selbst erstellt, also zu diesem Zeitpunkt Person.prototype.constructor === Objekt, das heißt:
function Person(name) { this.name = name; }; Person.prototype = { getName: function() { return this.name; } }; var p = new Person("haorooms"); console.log(p.constructor === Object); // true console.log(Person.prototype.constructor === Object); // true console.log(p.constructor.prototype.constructor === Object); // true
Wie kann dieses Problem behoben werden? Die Methode ist auch sehr einfach, überschreiben Sie einfach Person.prototype.constructor:
function Person(name) { this.name = name; }; Person.prototype = { getName: function() { return this.name; } }; Person.prototype.constructor = Person; var p = new Person("haorooms"); console.log(p.constructor === Person); // true console.log(Person.prototype.constructor === Person); // true console.log(p.constructor.prototype.constructor === Person); // true
kann auch so geschrieben werden:
function Person(name) { this.name = name; }; Person.prototype = { constructor:Person,//指定constructor getName: function() { return this.name; } };
Die obige umfassende Analyse dieses Klischees, des Konstruktors und des Prototyps von js ist der gesamte vom Herausgeber geteilte Inhalt. Ich hoffe, dass er Ihnen eine Referenz geben kann, und ich hoffe auch, dass jeder Script Home unterstützt.