J'ai promis d'expliquer l'héritage JavaScript, mais cela a été retardé jusqu'à présent. Sans plus attendre, allons droit au but.
Puisque vous voulez comprendre l'héritage, cela prouve que vous avez déjà une certaine compréhension du JavaScript orienté objet. Si vous ne comprenez toujours rien, vous pouvez vous référer à "Explication de base du JS orienté objet, mode usine, mode constructeur, mode prototype, mode mixte, mode prototype dynamique 》, parlons des méthodes généralement utilisées pour compléter l'héritage JavaScript.
Chaîne prototype
Le moyen le plus simple d'implémenter l'héritage en JavaScript est d'utiliser la chaîne de prototypes. Pointez simplement le prototype du sous-type vers l'instance du type parent, c'est-à-dire "subtype.prototype = new parent type ();". la méthode de mise en œuvre est la suivante :
// 为父类型创建构造函数 function SuperType() { this.name = ['wuyuchang', 'Jack', 'Tim']; this.property = true; } // 为父类型添加方法 SuperType.prototype.getSuerperValue = function() { return this.property; } // 为子类型创建构造函数 function SubType() { this.test = ['h1', 'h2', 'h3', 'h4']; this.subproperty = false; } // 实现继承的关键步骤,子类型的原型指向父类型的实例 SubType.prototype = new SuperType(); // 在此处给子类型添加方法,一定要在实现继承之后,否则会在将指针指向父类型的实例,则方法为空 SubType.prototype.getSubValue = function() { return this.subproperty; } /* 以下为测试代码示例 */ var instance1 = new SubType(); instance1.name.push('wyc'); instance1.test.push('h5'); alert(instance1.getSuerperValue()); // true alert(instance1.getSubValue()); // false alert(instance1.name); // wuyuchang,Jack,Tim,wyc alert(instance1.test); // h1,h2,h3,h4,h5 var instance2 = new SubType(); alert(instance2.name); // wuyuchang,Jack,Tim,wyc alert(instance2.test); // h1,h2,h3,h4
Explication de base du JS orienté objet, mode usine, mode constructeur, mode prototype, mode hybride, mode prototype dynamique" doivent connaître l'existence du code de la chaîne prototypeLe premier problème est que, comme le prototype du sous-type est une instance du type parent, c'est-à-dire les attributs du type parent contenus dans le prototype du sous-type, les attributs du prototype de la valeur du type référence seront être partagé par toutes les instances . L'instance1.name.push('wyc'); du code ci-dessus peut prouver l'existence de ce problème. Le deuxième problème avec la chaîne de prototypes est : Lors de la création d'une instance d'un sous-type, les paramètres ne peuvent pas être transmis au constructeur du supertype. Par conséquent, dans le développement réel, nous utilisons rarement la chaîne de prototypes seule.
Emprunter le constructeur
Afin de résoudre les deux problèmes existant dans la chaîne de prototypes, les développeurs ont commencé à utiliser une technique appelée constructeurs empruntés pour résoudre les problèmes existant dans la chaîne de prototypes. L'idée d'implémentation de cette technologie est également assez simple. Il suffit d'appeler le constructeur du type parent au sein du constructeur du sous-type. N'oubliez pas qu'une fonction est juste un objet qui exécute du code dans un environnement spécifique, vous pouvez doncexécuter un constructeur via la méthode apply() ou call(). Le code est le suivant :
// 为父类型创建构造函数 function SuperType(name) { this.name = name; this.color = ['pink', 'yellow']; this.property = true; this.testFun = function() { alert('http://tools.jb51.net/'); } } // 为父类型添加方法 SuperType.prototype.getSuerperValue = function() { return this.property; } // 为子类型创建构造函数 function SubType(name) { SuperType.call(this, name); this.test = ['h1', 'h2', 'h3', 'h4']; this.subproperty = false; } // 在此处给子类型添加方法,一定要在实现继承之后,否则会在将指针指向父类型的实例,则方法为空 SubType.prototype.getSubValue = function() { return this.subproperty; } /* 以下为测试代码示例 */ var instance1 = new SubType(['wuyuchang', 'Jack', 'Nick']); instance1.name.push('hello'); instance1.test.push('h5'); instance1.color.push('blue'); instance1.testFun(); // http://tools.jb51.net/ alert(instance1.name); // wuyuchang,Jack,Nick,hello // alert(instance1.getSuerperValue()); // error 报错 alert(instance1.test); // h1,h2,h3,h4,h5 alert(instance1.getSubValue()); // false alert(instance1.color); // pink,yellow,blue var instance2 = new SubType('wyc'); instance2.testFun(); // http://tools.jb51.net/ alert(instance2.name); // wyc // alert(instance2.getSuerperValue()); // error 报错 alert(instance2.test); // h1,h2,h3,h4 alert(instance2.getSubValue()); // false alert(instance2.color); // pink,yellow
instancie le sous-type, il est toujours incapable d'appeler la méthode getSuperValue définie dans le prototype du type parent. Il ne peut appeler que la méthode constructeur du type parent : testFun. . Cela revient à utiliser uniquement le modèle de constructeur lors de la création d'objets, ce qui rend la fonction non réutilisable. Compte tenu de ces problèmes, la technique de l’emprunt aux constructeurs est rarement utilisée seule.
Héritage combiné (constructeur emprunté de chaîne de prototypes)
Comme son nom l'indique, l'héritage combiné est un modèle qui combine les avantages de l'utilisation de la chaîne de prototypes et de l'emprunt de constructeurs. L'implémentation est également très simple. Puisqu'il s'agit d'une combinaison, elle combine certainement les avantages des deux parties, c'est-à-dire la méthode d'héritage de la chaîne prototypeet la propriété d'héritage du constructeur . L'implémentation spécifique du code est la suivante :
// 为父类型创建构造函数 function SuperType(name) { this.name = name; this.color = ['pink', 'yellow']; this.property = true; this.testFun = function() { alert('http://tools.jb51.net/'); } } // 为父类型添加方法 SuperType.prototype.getSuerperValue = function() { return this.property; } // 为子类型创建构造函数 function SubType(name) { SuperType.call(this, name); this.test = ['h1', 'h2', 'h3', 'h4']; this.subproperty = false; } SubType.prototype = new SuperType(); // 在此处给子类型添加方法,一定要在实现继承之后,否则会在将指针指向父类型的实例,则方法为空 SubType.prototype.getSubValue = function() { return this.subproperty; } /* 以下为测试代码示例 */ var instance1 = new SubType(['wuyuchang', 'Jack', 'Nick']); instance1.name.push('hello'); instance1.test.push('h5'); instance1.color.push('blue'); instance1.testFun(); // http://tools.jb51.net/ alert(instance1.name); // wuyuchang,Jack,Nick,hello alert(instance1.getSuerperValue()); // true alert(instance1.test); // h1,h2,h3,h4,h5 alert(instance1.getSubValue()); // false alert(instance1.color); // pink,yellow,blue var instance2 = new SubType('wyc'); instance2.testFun(); // http://tools.jb51.net/ alert(instance2.name); // wyc alert(instance2.getSuerperValue()); // true alert(instance2.test); // h1,h2,h3,h4 alert(instance2.getSubValue()); // false alert(instance2.color); // pink,yellow
Héritage prototype
La méthode d'implémentation de l'héritage prototypique est différente de celle de l'héritage prototypique n'utilise pas de constructeur au sens strict, mais utilise des prototypes pour créer de nouveaux objets basés sur des objets existants sans avoir à les créer. . Le code spécifique est le suivant :
function object(o) { function F() {} F.prototype = o; return new F(); }
/* 原型式继承 */ function object(o) { function F() {} F.prototype = o; return new F(); } var person = { name : 'wuyuchang', friends : ['wyc', 'Nicholas', 'Tim'] } var anotherPerson = object(person); anotherPerson.name = 'Greg'; anotherPerson.friends.push('Bob'); var anotherPerson2 = object(person); anotherPerson2.name = 'Jack'; anotherPerson2.friends.push('Rose'); alert(person.friends); // wyc,Nicholas,Tim,Bob,Rose
Héritage parasitaire
/* 寄生式继承 */ function createAnother(original) { var clone = object(original); clone.sayHi = function() { alert('hi'); } return clone; }
/* 原型式继承 */ function object(o) { function F() {} F.prototype = o; return new F(); } /* 寄生式继承 */ function createAnother(original) { var clone = object(original); clone.sayHi = function() { alert('hi'); } return clone; } var person = { name : 'wuyuchang', friends : ['wyc', 'Nicholas', 'Rose'] } var anotherPerson = createAnother(person); anotherPerson.sayHi();
寄生组合式继承
前面说过了JavaScrip中组合模式实现继承的缺点,现在我们就来解决它的缺点,实现思路是,对于构造函数继承属性,而原型链的混成形式继承方法,即不用在继承方法的时候实例化父类型的构造函数。代码如下:
function object(o) { function F() {} F.prototype = o; return new F(); } /* 寄生组合式继承 */ function inheritPrototype(subType, superType) { var prototype = object(superType.prototype); prototype.constructor = subType; subType.prototype = prototype; }
而在使用时只需要将组合模式中的“SubType.prototype = new SuperType();”这行代码替换成inheritPrototype(subType, superType);即可。寄生组合式继承的高效率体现在它只调用了一次父类型构造函数,避免了创建不必要的或多余的属性。与此同时,原型链还能保持不变,因此,还能够正常使用instanceof和isPrototypeof()。这也是目前来说最理想的继承方式了,目前也在向这种模式转型。(YUI也使用了这种模式。)
此博文参考《JavaScript高级程序设计第3版》,代码为经过改写,更具体,并加了注释使大家更易懂。如对JS继承方面有独到见解的童鞋不别吝啬,回复您的见解供大家参考!