Maison > Article > interface Web > Apprendre les modèles de conception JavaScript (héritage)_compétences Javascript
1. Héritage
L'héritage en JavaScript est un sujet très complexe, bien plus complexe que l'héritage dans tout autre langage orienté objet. Dans la plupart des autres langages orientés objet, hériter d’une classe nécessite uniquement l’utilisation d’un mot-clé. Contrairement à eux, afin d'atteindre l'objectif d'hériter des membres publics en JavaScript, une série de mesures doivent être prises. De plus, JavaScript est l'un des rares langages à utiliser l'héritage prototypique. Grâce à la flexibilité du langage, vous pouvez utiliser soit l'héritage standard basé sur les classes, soit l'héritage prototypique plus subtil.
2. Pourquoi l'héritage est-il nécessaire ?
De manière générale, lors de la conception des classes, nous espérons réduire le code répétitif et essayer d'affaiblir le couplage entre les objets. L'utilisation de l'héritage répond aux besoins du principe de conception précédent. Avec ce mécanisme, vous pouvez concevoir sur la base de classes existantes et profiter des méthodes dont elles disposent déjà, et il est plus facile de modifier la conception. Supposons que vous ayez besoin de plusieurs classes pour avoir une méthode toString() qui génère la structure de classe d'une manière spécifique. Bien sûr, vous pouvez copier et coller le code qui définit la méthode toString() dans chaque classe, mais si vous faites cela, à chaque fois. vous devez changer le fonctionnement de cette méthode, vous devrez répéter la même modification dans chaque classe. D'un autre côté, si vous fournissez une classe ToStringProvider et laissez ensuite ces classes hériter de cette classe, la méthode toString ne doit être déclarée qu'à un seul endroit.
Le fait qu'une classe hérite d'une autre classe peut conduire à un couplage fort entre les deux, c'est-à-dire qu'une classe dépend de l'implémentation interne de l'autre classe. Nous aborderons certaines techniques qui peuvent aider à éviter ce problème, notamment l'utilisation de classes dopantes pour fournir des méthodes à d'autres classes.
3. Héritage basé sur les classes
Regardez le code ci-dessous :
<script type="text/javascript"> function Person(name, age) { this.name = name; this.age = age; } Person.prototype.say = function () { console.log(this.name + " , " + this.age); } function Student(no) { this.no = no; } /** * Student的prototype指向Person的对象 */</span> Student.prototype = new Person(); var stu1 = new Student("0001"); stu1.name = '张三'; stu1.age = '11'; console.log(stu1.no); stu1.say(); </script>
Résultat de sortie :
Zhang San, 11 ans
Vous pouvez voir que Student a intégré avec succès Person et dispose de la méthode say de Person. Le code de base est en fait Student.prototype = new Person();. >
Pointez Student.prototype vers new Person(), et le _proto_ de new Person pointe vers Person Prototype ; cela complète l'héritage complet.
Mais il y a des problèmes avec cette approche :
Problème 1 : Lorsque la classe parent a une variable de type référence, les données sont incohérentes. Ensuite, nous ajoutons un attribut hobbies à Person, dont le type est un tableau.
<script type="text/javascript"> /** * 存在问题 * 1、无法在Student的构造方法中传递参数用于父类的构造方法 * 2、对于引用类型变量,造成数据不一致 */ function Person(name, age) { this.name = name; this.age = age; this.hobbies = [] ; } Person.prototype.say = function () { console.log(this.name + " , " + this.age +" , " +this.hobbies); } function Student(no) { this.no = no; } Student.prototype = new Person(); var stu1 = new Student("0001"); stu1.name = '张三'; stu1.age = '11'; stu1.hobbies.push("soccer"); stu1.say(); var stu2 = new Student("0002"); stu2.name = '李四'; stu2.age = '12'; stu2.hobbies.push("girl"); stu2.say(); </script>
Zhang San, 11 ans, football
Li Si, 12 ans, football, fille
On peut voir que les passe-temps de John Doe ne devraient être que des filles, mais le code ci-dessus permet à tous les objets de partager l'attribut de passe-temps.
Il y a toujours un problème avec la méthode d'héritage ci-dessus :
Question 2 : Dans le constructeur de Student, new Student("00001", "Zhang San", 12) ne peut pas être utilisé pour créer un objet et initialiser le nom et ; age Les attributs doivent être attribués stu.name, stu.age
Afin de résoudre le problème ci-dessus, modifiez le code ci-dessus :
<script type="text/javascript"> function Person(name, age) { this.name = name; this.age = age; this.hobbies = []; } Person.prototype.say = function () { console.log(this.name + " , " + this.age +" , " + this.hobbies); } function Student(name, age, no) { /** * 使用call方法,第一个参数为上下文; * 有点类似Java中的super(name,age)的感觉 */ Person.call(this, name, age); this.no = no; } Student.prototype = new Person(); var stu1 = new Student("0001","张三",11); stu1.hobbies.push("soccer"); stu1.say(); var stu2 = new Student("0002","李四",12); stu2.hobbies.push("cangjin"); stu2.hobbies.push("basketball"); stu2.say(); </script>
0001, Zhang San, football
0002, Li Si, cangjin, basket
L'utilisation de Person.call(this,name,age) dans le constructeur Student ressemble à super(name,age) [le premier paramètre de l'appel est le contexte] et résout avec succès le problème de partage d'attributs de référence ; est parfaitement résolu.
4. Héritage basé sur une chaîne de prototypes
<script type="text/javascript"> /** * 基于原型链的集成中都是对象 * 存在问题: * 1、对于引用类型变量,造成数据不一致 */ var Person = { name: "人", age: 0, hobbies: [], say: function () { console.log(this.name + " , " + this.age + " , " + this.hobbies); } } ; var Student = clone(Person); Student.no =""; Student.sayHello = function() { console.log(this.name +"hello ") ; } var stu1 = clone(Student); stu1.name = "zhangsan"; stu1.age = 12; stu1.hobbies.push("Java"); stu1.say(); var stu2 = clone(Student); stu2.name = "lisi"; stu2.age = 13; stu2.hobbies.push("Javascript"); stu2.say(); /** * 返回一个prototype执行obj的一个对象 * @param obj * @returns {F} */ function clone(obj) { var F = function () { }; F.prototype = obj; return new F(); } </script>
zhangsan, 12 ans, Java
lisi, 13 ans, Java,Javascript
On voit qu'il y a aussi le problème des attributs de référence incohérents, et toute l'opération est basée sur des objets, ce qui ne donne pas une bonne impression aux gens. Le principe est expliqué ci-dessous à travers des schémas :
Les objets renvoient continuellement un nouvel objet via une fonction de clonage, et le prototype exécute l'objet entrant. L'ensemble du processus d'héritage est en fait _proto_ pointant constamment pour former une chaîne, c'est pourquoi on l'appelle une chaîne de prototypes.
D'accord, nous l'avons introduit. Parmi les deux méthodes d'intégration de js, la meilleure consiste à utiliser l'héritage de classe, qui est relativement stable.
Ce qui précède est une introduction aux points de connaissances pertinents sur l'héritage. J'espère que cela sera utile à l'apprentissage de chacun.