Prototipo y cadena de prototipos con un profundo conocimiento de JavaScript

Escribir en frente

Los prototipos y las cadenas de prototipos siempre han sido conceptos importantes en JavaScript. Comprenderlos nos ayuda a comprender la relación entre los tipos de referencia predefinidos y el mecanismo de implementación de la herencia de objetos en JavaScript. Lo siguiente es mi comprensión y resumen de prototipos y cadenas de prototipos.

Prototipo

Prototipo de comprensión de objetos

La propiedad prototipo del objeto de función

Cada función que creamos tiene un atributo prototipo, que es un puntero a un objeto. El propósito de este objeto es contener propiedades y métodos que puedan ser compartidos por todas las instancias de un tipo específico. En resumen, las propiedades __proto__ de todos los objetos instanciados por la función apuntan a este objeto, que es el prototipo de todos los objetos instanciados de la función .

function Person(){
}
// 为原型对象添加方法Person.prototype.sayName = function(){ alert(this.name);}

Veamos la relación entre ellos.

propiedad constructora

Cuando se crea la función y la propiedad del prototipo apunta a un objeto prototipo, de forma predeterminada, el objeto prototipo obtendrá una propiedad de constructor, que es un puntero al objeto de la función donde se encuentra el prototipo.

Tomando el ejemplo anterior, Person.prototype.constructor apunta al objeto de función Person.

Actualicemos el diagrama de relación entre ellos.

Atributo __proto__ del objeto

Cuando llamamos al constructor para crear una nueva instancia, contendrá un puntero dentro de la instancia que apunta al objeto prototipo del constructor. Este puntero se llama [[Prototype]] en la quinta edición de ECMA-262. Todos los objetos contienen el atributo [[Prototipo]], que apunta a su objeto prototipo, que es un concepto clave para comprender la cadena del prototipo.

Cabe señalar que no hay una forma estándar de acceder a la propiedad [[Prototype]] en el script, pero cada objeto en Firefox, Safari y Chrome admite una propiedad __proto__ para acceder, a fin de distinguir la propiedad prototype, usamos a continuación __proto__ para expresar.

Según el constructor de Persona anterior, creamos una nueva instancia

var student = new Person();

console.log(student.__proto__ === Person.prototype); // true

Como podemos ver en lo anterior, esta conexión existe entre la instancia y el objeto prototipo del constructor, no entre la instancia y el constructor.

Echemos un vistazo a la relación entre estos objetos.

isPrototypeOf ()

Aunque no tenemos forma de acceder a la propiedad [[Prototype]] en el script, podemos usar el método isPrototypeOf para determinar si esta relación existe entre los objetos.

El método isPrototypeOf () se usa para probar si un objeto existe en la cadena prototipo de otro objeto.

console.log(Person.prototype.isPrototypeOf(student)); // true

Object.getPrototypeOf ()

Se ha agregado un nuevo método llamado Object.getPrototypeOf () en ECMAScript 5, este método puede devolver el valor de [[Prototype]] de la siguiente manera

console.log(Object.getPrototypeOf(student) === Person.prototype); // true

Atributo prototipo

Acceso de atributo

Siempre que el código lea un atributo de un objeto, primero buscará el atributo en el objeto mismo, y si se encuentra el atributo, devuelve el valor del atributo, si no se encuentra, continúe buscando el objeto prototipo correspondiente al objeto, y así sucesivamente. .

Debido a este proceso de búsqueda, si agregamos un atributo a la instancia, este atributo protegerá el atributo con el mismo nombre guardado en el objeto prototipo, porque después de buscar el atributo en la instancia, no buscaremos hacia atrás.

Juicio de atributos

Dado que un atributo puede ser la instancia misma o su objeto prototipo, ¿cómo lo juzgamos?

En el caso en que la propiedad confirme la existencia, podemos usar el método hasOwnProperty () para determinar si existe una propiedad en la instancia o en el prototipo. Tenga en cuenta que este método solo devuelve verdadero si el atributo dado existe en la instancia.

function Person() {};
Person.prototype.name = "laker" ;
var student = new Person();
console.log(student.name); // lakerconsole.log(student.hasOwnProperty("name")); // false

student.name = "xiaoming";console.log(student.name); //xiaoming 屏蔽了原型对象中的 name 属性console.log(student.hasOwnProperty("name")); // true

Lo anterior es principalmente para el caso en el que se confirma que el atributo existe. Si este atributo no existe necesariamente, el juicio no es lo suficientemente exacto. Por lo tanto, primero debemos determinar si el atributo existe y luego realizar la operación de juicio anterior.

Para determinar si existe un atributo, podemos usar el operador in, que devuelve verdadero cuando el objeto puede acceder a un atributo dado, independientemente de si el atributo existe en la instancia o prototipo.

Por lo tanto, podemos encapsular dicha función para determinar si existe una propiedad en el prototipo.

function hasPrototypeProperty(object, name){ return !object.hasOwnProperty(name) && (name in object);}

bucle for-in

Cuando se utiliza un bucle for-in, se devuelven todos los atributos enumerables a los que se puede acceder a través del objeto, incluidos los atributos que existen en la instancia y los atributos que existen en el prototipo.

Una cosa a tener en cuenta es que los atributos de instancia que enmascaran atributos no enumerables en la instancia también se devolverán en un bucle for-in.

Obtén todos los atributos

Si desea obtener todas las propiedades de instancia enumerables en un objeto, puede usar el método Object.keys (). Este método recibe un objeto como parámetro y devuelve una matriz de cadena que contiene todas las propiedades enumerables.

Si desea obtener todas las propiedades de la instancia, ya sea que se puedan enumerar o no, podemos usar el método Object.getOwnPropertyNames ().

Cadena prototipo

Comprender la cadena de prototipos

El concepto de cadena de prototipo se describe en ECMAScript, y la cadena de prototipo se usa como el método principal para lograr la herencia. La idea básica es usar un tipo de referencia para heredar las propiedades y métodos de otro tipo de referencia.

El principal método de implementación de la cadena de prototipos es hacer que el objeto prototipo del constructor sea igual a una instancia de otro tipo. Dado que el objeto prototipo en este momento es una instancia, contendrá un puntero a otro prototipo y, en consecuencia, otro prototipo también contiene un Puntero a otro constructor. Si otro prototipo es una instancia de otro tipo, entonces la relación anterior aún se establece, de modo que las capas de progresividad forman una cadena de instancias y tipos. Este es el concepto básico de la cadena prototipo.

Veamos un ejemplo.

function Super(){};function Middle(){};function Sub(){};Middle.prototype = new Super();Sub.prototype = new Middle();var suber = new Sub();

Echemos un vistazo a la relación entre estos objetos.

Prototipo predeterminado

De hecho, nuestra cadena de prototipos anterior está incompleta. ¿Recuerdas cómo dijimos que todos los tipos de referencia heredan Object? Esta herencia se logra a través de la cadena prototipo. Debemos recordar que el prototipo predeterminado de todas las funciones es una instancia de Object, por lo que el prototipo predeterminado contendrá un puntero interno a Object.Prototype. Esta es la razón fundamental por la que todos los tipos personalizados heredan los métodos predeterminados, como toString () y valueOf ().

Luego actualizo la cadena de prototipos sobre nosotros.

Object.prototype es el final de la cadena de prototipos, podemos intentar imprimir Object.prototype .__ proto__, encontraremos que devuelve un objeto vacío nulo, lo que significa el final de la cadena de prototipos.

Las funciones también son objetos.

De hecho, la cadena de prototipos anterior todavía falta, ¿por qué? Porque sabemos que en JavaScript, las funciones también son objetos, por lo que las funciones también deben tener sus objetos prototipo. Comprendamos la relación entre ellos a través de un ejemplo.

Código de ejemplo:

function Foo(who) {this.me = who;}
Foo.prototype.identify = function() {return "I am " + this.me;};
function Bar(who) {Foo.call( this, who );}
Bar.prototype = Object.create( Foo.prototype );
Bar.prototype.speak = function() {alert( "Hello, " + this.identify() + "." );};
var b1 = new Bar( "b1" );var b2 = new Bar( "b2" );
b1.speak();b2.speak();

Primero veamos el diagrama de relación de la cadena de prototipos incluida en el ejemplo anterior sin la función prototipo:

El siguiente es el diagrama de relación de la cadena del prototipo después de agregar el prototipo de función.

Escribe al final

Después de resumir el conocimiento de los prototipos y las cadenas de prototipos, siento que la comprensión del lenguaje JavaScript es más profunda, y también sienta las bases para comprender la creación y la herencia de objetos más adelante. De hecho, para comprender la cadena de prototipos, es fácil comprender el comportamiento y la implementación de algunos tipos predefinidos en JavaScript.

117 artículos originales publicados · 69 alabanzas · 10,000+ vistas

Supongo que te gusta

Origin blog.csdn.net/zsd0819qwq/article/details/105378892
Recomendado
Clasificación