Vorwort
JS ist eine objektorientierte, schwach typisierte Sprache, und Vererbung ist ebenfalls eine ihrer sehr leistungsstarken Funktionen. Wie implementiert man also die Vererbung in JS? Warten wir ab.
Da wir die Vererbung implementieren möchten, müssen wir zunächst eine übergeordnete Klasse haben. Der Code lautet wie folgt:
// 定义一个动物类 function Animal (name) { // 属性 this.name = name || 'Animal'; // 实例方法 this.sleep = function(){ console.log(this.name + '正在睡觉!'); } } // 原型方法 Animal.prototype.eat = function(food) { console.log(this.name + '正在吃:' + food); };
Kern: Verwenden Sie die Instanz der übergeordneten Klasse als Prototyp der Unterklasse
function Cat(){ } Cat.prototype = new Animal(); Cat.prototype.name = 'cat'; // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.eat('fish')); console.log(cat.sleep()); console.log(cat instanceof Animal); //true console.log(cat instanceof Cat); //true
Eigenschaften:
Sehr reine Vererbungsbeziehung, die Instanz ist eine Instanz der Unterklasse und auch eine Instanz der übergeordneten Klasse
Die übergeordnete Klasse verfügt über hinzugefügte Prototypmethoden/Prototypattribute, auf die zugegriffen werden kann nach Unterklassen
Einfach und leicht zu implementieren
Nachteile:
Wenn Sie hinzufügen möchten Attribute und Methoden zu einer Unterklasse hinzufügen, müssen Sie sie hinzufügen new
Animal()
Eine solche Anweisung wird später ausgeführt und kann nicht im Konstruktor platziert werden
Mehrfachvererbung kann nicht implementiert werden
Referenzeigenschaften aus dem Prototypobjekt werden von allen Instanzen gemeinsam genutzt (Einzelheiten finden Sie im Anhangcode: Beispiel 1)
Beim Erstellen einer Unterklasseninstanz können Parameter nicht verwendet werden an den Konstruktor der übergeordneten Klasse übergeben werden
Empfohlener Index: ★★ (zwei schwerwiegende Fehler von 3 und 4)
Kern: Verwenden Sie den Konstruktor der übergeordneten Klasse, um die Instanz der Unterklasse zu erweitern, die gleich ist. Es dient dazu, die Instanzattribute der übergeordneten Klasse in die Unterklasse zu kopieren (es wird kein Prototyp verwendet)
<p style="margin-top: 15px;">function Cat(name){<br> Animal.call(this);<br> this.name = name || 'Tom';<br>}<br><br>// Test Code<br>var cat = new Cat();<br>console.log(cat.name);<br>console.log(cat.sleep());<br>console.log(cat instanceof Animal); // false<br>console.log(cat instanceof Cat); // true<br></p>
Funktionen:
Lösen Sie 1, Unterklasseninstanzen teilen sich die übergeordnete Klasse. Probleme mit Referenzattributen
Beim Erstellen einer Unterklasseninstanz können Sie Parameter an die übergeordnete Klasse übergeben
Mehrfachvererbung kann erreicht werden (rufen Sie mehrere übergeordnete Klassen auf)
Nachteile:
Instanz ist keine Instanz der übergeordneten Klasse, sondern eine Instanz der Unterklasse
Nur die Instanzattribute und -methoden der übergeordneten Klasse können vererbt und als Prototyp verwendet werden Attribute/Methoden können nicht vererbt werden
Funktionswiederverwendung kann nicht erreicht werden. Jede Unterklasse hat eine Kopie der Instanzfunktion der übergeordneten Klasse
Empfehlungsindex: ★★ (Nachteil 3)
核心:为父类实例添加新特性,作为子类实例返回
function Cat(name){ var instance = new Animal(); instance.name = name || 'Tom'; return instance; } // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // true console.log(cat instanceof Cat); // false
特点:
不限制调用方式,不管是new
子类()
还是子类()
,返回的对象具有相同的效果
缺点:
实例是父类的实例,不是子类的实例
不支持多继承
推荐指数:★★
function Cat(name){ var animal = new Animal(); for(var p in animal){ Cat.prototype[p] = animal[p]; } Cat.prototype.name = name || 'Tom'; } // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // false console.log(cat instanceof Cat); // true
特点:
支持多继承
缺点:
效率较低,内存占用高(因为要拷贝父类的属性)
无法获取父类不可枚举的方法(不可枚举方法,不能使用for in 访问到)
推荐指数:★(缺点1)
核心:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用
function Cat(name){ Animal.call(this); this.name = name || 'Tom'; } Cat.prototype = new Animal(); // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // true console.log(cat instanceof Cat); // true
特点:
弥补了方式2的缺陷,可以继承实例属性/方法,也可以继承原型属性/方法
既是子类的实例,也是父类的实例
不存在引用属性共享问题
可传参
函数可复用
缺点:
调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了)
推荐指数:★★★★(仅仅多消耗了一点内存)
核心:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点
function Cat(name){ Animal.call(this); this.name = name || 'Tom'; } (function(){ // 创建一个没有实例方法的类 var Super = function(){}; Super.prototype = Animal.prototype; //将实例作为子类的原型 Cat.prototype = new Super(); })(); // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // true console.log(cat instanceof Cat); //true
特点:
堪称完美
缺点:
实现较为复杂
推荐指数:★★★★(实现复杂,扣掉一颗星)
示例一:
function Animal (name) { // 属性 this.name = name || 'Animal'; // 实例方法 this.sleep = function(){ console.log(this.name + '正在睡觉!'); } //实例引用属性 this.features = []; } function Cat(name){ } Cat.prototype = new Animal(); var tom = new Cat(); var kissy = new Cat(); console.log(tom.name); // "Animal" console.log(kissy.name); // "Animal" console.log(tom.features); // [] console.log(kissy.features); // [] tom.name = 'Tom-New Name'; tom.features.push('eat'); //针对父类实例值类型成员的更改,不影响 console.log(tom.name); // "Tom-New Name" console.log(kissy.name); // "Animal" //针对父类实例引用类型成员的更改,会通过影响其他子类实例 console.log(tom.features); // ['eat'] console.log(kissy.features); // ['eat'] 原因分析: 关键点:属性查找过程 执行tom.features.push,首先找tom对象的实例属性(找不到), 那么去原型对象中找,也就是Animal的实例。发现有,那么就直接在这个对象的 features属性中插入值。 在console.log(kissy.features); 的时候。同上,kissy实例上没有,那么去原型上找。 刚好原型上有,就直接返回,但是注意,这个原型对象中features属性值已经变化了。
Das obige ist der detaillierte Inhalt vonMehrere Möglichkeiten zur Implementierung der Vererbung in JS. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!