Maison  >  Article  >  interface Web  >  Entretien JS Questions fréquemment posées Prototype et chaîne de prototypes

Entretien JS Questions fréquemment posées Prototype et chaîne de prototypes

little bottle
little bottleoriginal
2019-04-29 17:52:008904parcourir

Le prototype et la chaîne de prototypes sont l'une des questions d'entretien frontales les plus fréquentes. Je pense que de nombreux amis ont rencontré ce problème. Alors, le comprenez-vous clairement et complètement ?

[Recommandations associées : Questions d'entretien frontales]

Pratique internationale, posons d'abord la question :

  • Qu'est-ce que Prototype, chaîne de prototypes
  • Quelles sont leurs caractéristiques
  • Que peuvent-ils faire
  • Comment déterminer leur relation

Peut-être que vous l'avez déjà la réponse, Peut-être que vous commencez à avoir des doutes, qu'il s'agisse get d'une nouvelle compétence ou d'une simple révision, explorons-la ensemble

S'il y a des omissions ou des erreurs dans l'article, veuillez consulter Merci à l'avance pour vos conseils.

Le prototype

JavaScript est basé sur le prototype

Chaque fonction que nous créons a un attribut prototype(原型), qui est un pointeur, pointe vers un objet dont le but est de contenir des propriétés et des méthodes pouvant être partagées par toutes les instances d'un type particulier.

Pour faire simple, lorsque nous créons une fonction, le système attribuera automatiquement un prototype attribut, qui peut être utilisé pour stocker des attributs et des méthodes pouvant être partagés par toutes les instances

Il sera plus clair de l'exprimer avec une image :

Entretien JS Questions fréquemment posées Prototype et chaîne de prototypes

Illustration :

  • Chaque Les constructeurs ont tous un attribut prototype, qui pointe vers un objet, c'est-à-dire l'objet prototype
  • L'objet prototype a un attribut constructor par défaut, pointant vers le constructeur qui pointe vers lui
  • Chaque Chaque objet a un attribut caché __proto__, pointant vers son objet prototype
function Person(){}

var p = new Person();

p.__proto__ === Person.prototype // true

Person.prototype.constructor === Person // true

Alors, quelles sont les caractéristiques de l'objet prototype

Caractéristiques du prototype
function Person(){}
Person.prototype.name = 'tt';
Person.prototype.age = 18;
Person.prototype.sayHi = function() {
    alert('Hi');
}
var person1 = new Person();
var person2 = new Person();
person1.name = 'oo';
person1.name // oo
person1.age // 18
perosn1.sayHi() // Hi
person2.age // 18
person2.sayHi() // Hi

Ce n'est pas difficile à voir à partir de ce code :

    Les instances peuvent partager les attributs et les méthodes sur le prototype
  • Les attributs de l'instance elle-même bloqueront les attributs du même nom sur le prototype, et celles qui ne sont pas sur l'instance. Les propriétés se retrouveront sur le prototype
Puisque le prototype est aussi un objet, peut-on remplacer cet objet ? La réponse est oui

function Person() {}
Person.prototype = {
    name: 'tt',
    age: 18,
    sayHi() {
        console.log('Hi');
    }
}

var p = new Person()

Mais nous devons prêter attention aux problèmes suivants lors de la réécriture de la chaîne de prototypes :

function Person(){}
var p = new Person();
Person.prototype = {
    name: 'tt',
    age: 18
}

Person.prototype.constructor === Person // false

p.name // undefined

Une image vaut mille mots

Entretien JS Questions fréquemment posées Prototype et chaîne de prototypes

    Remplacer le prototype alors qu'une instance a déjà été créée coupera la connexion entre l'instance existante et le nouveau prototype
  • Réécrire l'objet prototype, cela fait que l'attribut
  • de l'objet prototype pointe vers constructor, provoquant le chaos dans la chaîne de prototypes. Par conséquent, nous devons spécifier Object lors du remplacement de l'objet prototype ( constructor renverra toujours la valeur correcte) instanceof
    Person.prototype = {
        constructor: Person
    }
  • REMARQUE : Réinitialiser un attribut
de cette manière entraînera la définition de son attribut

sur constructor (la valeur par défaut est Enumerable) truefalse Maintenant que nous savons qu'est-ce que c'est

et ses caractéristiques, alors c'est quoi la chaîne prototype ? Tous les objets de la

prototype(原型)chaîne de prototypes

sont hérités de son objet prototype. L'objet prototype lui-même est également un objet, et il possède également son propre objet prototype. De cette façon, une structure similaire à une liste chaînée est formée, qui est la chaîne prototype
JavaScriptDe même, nous utilisons une image pour décrire


Entretien JS Questions fréquemment posées Prototype et chaîne de prototypes

Le point final de toutes les chaînes prototypes est l'attribut
    de la fonction
  • Object prototype
  • L'objet prototype pointé a également un prototype, mais son prototype est
  • , alors que Objec.prototype n'a pas de prototype nullnull
  • Comprenant le concept de chaîne de prototypes, on peut savoir les attributs recherchent plus clairement les règles, comme l'attribut d'instance
précédent. Si cet attribut n'existe pas en lui-même ou dans la chaîne de prototypes, alors la valeur finale de l'attribut est

S'il s'agit d'une méthode, d'un. une erreur sera générée dans la pundefinedclass class

fournit le concept de
comme modèle pour les objets Grâce au mot-clé ES6, vous pouvez définir la classe Class(类)Pourquoi class est-il mentionné :
de 🎜>class peut être considéré comme un simple sucre de syntaxe. La plupart de ses fonctions peuvent être réalisées par . > La méthode d'écriture rend simplement la méthode d'écriture de prototype d'objet plus claire et plus orientée. Juste la syntaxe de la programmation objet

.

class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
}

// 可以这么改写
function Point(x, y) {
  this.x = x;
  this.y = y;
}

Point.prototype.toString = function () {
  return '(' + this.x + ', ' + this.y + ')';
};

class 里面定义的方法,其实都是定义在构造函数的原型上面实现实例共享,属性定义在构造函数中,所以 ES6 中的类完全可以看作构造函数的另一种写法

除去 class 类中的一些行为可能与 ES5 存在一些不同,本质上都是通过原型、原型链去定义方法、实现共享。所以,还是文章开始那句话  JavaScript是基于原型的

更多 class 问题,参考这里

关系判断

instanceof

最常用的确定原型指向关系的关键字,检测的是原型,但是只能用来判断两个对象是否属于实例关系, 而不能判断一个对象实例具体属于哪种类型

function Person(){}
var p = new Person();

p instanceof Person // true
p instanceof Object // true
hasOwnProperty

通过使用 hasOwnProperty 可以确定访问的属性是来自于实例还是原型对象

function Person() {}
Person.prototype = {
    name: 'tt'
}
var p = new Person();
p.age = 15;

p.hasOwnProperty('age') // true
p.hasOwnProperty('name') // false

原型链的问题

由于原型链的存在,我们可以让很多实例去共享原型上面的方法和属性,方便了我们的很多操作。但是原型链并非是十分完美的

function Person(){}
Person.prototype.arr = [1, 2, 3, 4];

var person1 = new Person();
var person2 = new Person();

person1.arr.push(5) 
person2.arr // [1, 2, 3, 4, 5]

引用类型,变量保存的就是一个内存中的一个指针。所以,当原型上面的属性是一个引用类型的值时,我们通过其中某一个实例对原型属性的更改,结果会反映在所有实例上面,这也是原型 共享 属性造成的最大问题

另一个问题就是我们在创建子类型(比如上面的 p)时,没有办法向超类型( Person )的构造函数中传递参数

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn