Maison  >  Article  >  interface Web  >  Une brève analyse de la relation entre __proto__ et prototype en JavaScript

Une brève analyse de la relation entre __proto__ et prototype en JavaScript

零到壹度
零到壹度original
2018-03-22 11:37:151114parcourir

Cette fois, je vais vous donner une brève analyse de la relation entre __proto__ et prototype en JavaScript. Ce qui suit est un cas pratique. Suivez l'éditeur pour y jeter un œil.

1. Le __proto__ de tous les constructeurs/fonctions pointe vers Function.prototype, qui est une fonction vide (Vide function)

Number.__proto__ === Function.prototype  // true
Boolean.__proto__ === Function.prototype // true
String.__proto__ === Function.prototype  // true
Object.__proto__ === Function.prototype  // true
Function.__proto__ === Function.prototype // true 
Array.__proto__ === Function.prototype   // true
RegExp.__proto__ === Function.prototype  // true
Error.__proto__ === Function.prototype   // true
Date.__proto__ === Function.prototype    // true

Il y a un total de 12 constructeurs/objets intégrés (intégrés) en JavaScript (JSON est nouvellement ajouté dans ES5). Voici 8 constructeurs accessibles. Le reste comme Global n'est pas accessible directement, les arguments ne sont créés par le moteur JS que lorsque la fonction est appelée, Math et JSON existent sous forme d'objets et n'en nécessitent pas de nouveaux. Leur __proto__ est Object.prototype. Comme suit

Math.__proto__ === Object.prototype  // true 
JSON.__proto__ === Object.prototype  // true

Les "tous les constructeurs/fonctions" mentionnés ci-dessus incluent certainement ceux personnalisés. Comme suit

// 函数声明
function Person() {}
// 函数表达式
var Man = function() {}
console.log(Person.__proto__ === Function.prototype) // true
console.log(Man.__proto__ === Function.prototype)    // true

Qu'est-ce que cela signifie ?

Tous les constructeurs proviennent de Function.prototype, même le constructeur racine Object et Function lui-même. Tous les constructeurs héritent des propriétés et méthodes de Function.prototype. Tels que la longueur, l'appel, l'application, la liaison (ES5).

Function.prototype est également le seul type de XXX.prototype est prototype de « fonction ». Le prototype des autres constructeurs est un objet. Par exemple :

console.log(typeof Function.prototype) // function
console.log(typeof Object.prototype)   // object
console.log(typeof Number.prototype)   // object
console.log(typeof Boolean.prototype)  // object
console.log(typeof String.prototype)   // object
console.log(typeof Array.prototype)    // object
console.log(typeof RegExp.prototype)   // object
console.log(typeof Error.prototype)    // object
console.log(typeof Date.prototype)     // object
console.log(typeof Object.prototype)   // object

Oh, il est également mentionné ci-dessus qu'il s'agit d'une fonction vide, jetons un œil à alert(Function.prototype).

Maintenant que nous savons que le __proto__ de tous les constructeurs (y compris ceux intégrés et personnalisés) est Function.prototype, alors qui est le __proto__ de Function.prototype ?

Je crois que vous avez tous entendu dire que les fonctions en JavaScript sont également des citoyens de premier ordre, alors comment pouvez-vous le montrer ? Comme indiqué ci-dessous

console.log(Function.prototype.__proto__ === Object.prototype) // true

Cela montre que tous les constructeurs sont également des objets JS ordinaires et que des attributs peuvent être ajoutés/supprimés au constructeur. En même temps, il hérite également de toutes les méthodes d'Object.prototype : toString, valueOf, hasOwnProperty, etc.

Qui est le __proto__ d'Object.prototype ?

Object.prototype.__proto__ === null  // true

a atteint le sommet et est nul.

2. Le __proto__ de tous les objets pointe vers le prototype de son constructeur

Ce qui précède teste le __proto__ de tous les constructeurs intégrés et personnalisés, comme suit. regardez à qui pointe le __proto__ des objets d'instance de tous ces constructeurs ?

Regardez d'abord le constructeur intégré du moteur JavaScript

var obj = {name: 'jack'}
var arr = [1,2,3]
var reg = /hello/g
var date = new Date
var err = new Error('exception')
console.log(obj.__proto__ === Object.prototype) // true
console.log(arr.__proto__ === Array.prototype)  // true
console.log(reg.__proto__ === RegExp.prototype) // true
console.log(date.__proto__ === Date.prototype)  // true
console.log(err.__proto__ === Error.prototype)  // true

Regardez ensuite le constructeur personnalisé, ici une personne est définie

function Person(name) {
this.name = name
}
var p = new Person('jack')
console.log(p.__proto__ === Person.prototype) // true

p est Person Pour les objets d'instance, le prototype interne de p pointe toujours vers le prototype de son constructeur Person.

Chaque objet a un attribut constructeur et son constructeur peut être obtenu, donc les résultats imprimés suivants sont également identiques

function Person(name) {
this.name = name
}
var p = new Person('jack')
console.log(p.__proto__ === p.constructor.prototype) // true

La personne ci - dessus n'ajoute pas d'attributs ou de méthodes à son prototype , ajoutez ici une méthode getName

function Person(name) {
this.name = name
}
// 修改原型
Person.prototype.getName = function() {}
var p = new Person('jack')
console.log(p.__proto__ === Person.prototype) // true
console.log(p.__proto__ === p.constructor.prototype) // true

à son prototype. Vous pouvez voir que p.__proto__, Person.prototype et p.constructor.prototype sont tous identiques, c'est-à-dire qu'ils pointent tous vers le même objet. .

Si vous définissez le prototype d'une autre manière, le résultat sera quelque peu différent

function Person(name) {
this.name = name
}
// 重写原型
Person.prototype = {
getName: function() {}
}
var p = new Person('jack')
console.log(p.__proto__ === Person.prototype) // true
console.log(p.__proto__ === p.constructor.prototype) // false

Person.prototype est directement réécrit ici (remarque : l'exemple précédent consiste à modifier le prototype). Le résultat montre que p.__proto__ pointe toujours vers Person.prototype, et non vers p.constructor.prototype.

C'est également facile à comprendre. Ce qui est attribué à Person.prototype est un littéral d'objet {getName : function(){}}, le constructeur d'un objet défini à l'aide de la méthode littérale d'objet pointe vers le constructeur racine Object, Object.prototype est un objet vide {}, {} est naturellement identique à {getName : function(){}} n'est pas égal. Comme suit

var p = {}
console.log(Object.prototype) // 为一个空的对象{}
console.log(p.constructor === Object) // 对象直接量方式定义的对象其constructor为Object
console.log(p.constructor.prototype === Object.prototype) // 为true,不解释

Le __proto__ utilisé dans le code ci-dessus n'est actuellement pas pris en charge dans IE6/7/8/9. Dans IE9, vous pouvez utiliser Object.getPrototypeOf(ES5) pour obtenir le prototype interne d'un objet.

var p = {}
var __proto__ = Object.getPrototypeOf(p)
console.log(__proto__ === Object.prototype) // true

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