En la mayoría de los lenguajes de programación, hay clases y objetos, y una clase puede heredar otras clases.
En JavaScript, la herencia está basada en prototipos, lo que significa que no hay clases en JavaScript, y en su lugar, un objeto hereda otro objeto. :)
1. Herencia, el Proto
En JavaScript, cuando un objeto conejo hereda otro animal objeto, significa que habrá una propiedad especial en el objeto de conejo: conejo .__ proto__ = animal;
Al acceder a un objeto de conejo, si el intérprete no puede encontrar la propiedad en el conejo, seguirá la cadena __proto__ para buscar en el objeto animal
El atributo __proto__ en castañas solo es accesible en Chrome y Firefox. Por favor vea una castaña:
var animal = {Eats: true} var conejo = {saltos: true} conejo .__ proto__ = animal // heredero (rabbit.eats) // trueSe accede al atributo Eats desde un objeto animal.
Si el atributo se ha encontrado en el objeto de conejo, no se verificará el atributo Proto.
Tengamos otra castaña. Cuando también hay un atributo EATS en la subclase, no se accederá a la clase principal.
var animal = {eats: true} var federprBbit = {eats: false} feduprBbit .__ proto__ = animal alerta (federprBbit.eats) // falsoTambién puede agregar una función en animal, y también se puede acceder en conejo.
var animal = {eat: function () {alerta ("Estoy lleno") this.full = true}} var rabbit = {salto: function () { / * something * /}} conejo .__ proto__ = animal(1) conejo.eat ():
La función Rabbit.eat () se ejecuta en los siguientes dos pasos:
Primero, el intérprete busca Rabbit.Eat. No hay función de comer en el conejo, por lo que mira hacia arriba a lo largo del conejo .__ Proto__ y la encontró en animal.
La función se ejecuta con este = conejo. Este valor no tiene nada que ver con el atributo __proto__.
Entonces esto.full = verdadero en conejo:
Veamos qué nuevos descubrimientos hemos hecho aquí. Un objeto llama a la función principal, pero esto todavía apunta al objeto en sí, que es herencia.
El objeto mencionado por __proto__ se llama prototipo, y el animal es el prototipo de conejo (nota del traductor: este es el atributo __proto__ de conejo se refiere al atributo prototipo de animal)
(2) Buscar al leer, no al escribir
Al leer un objeto, como este.prop, el intérprete busca propiedades en su prototipo.
Al establecer un valor de atributo, como este.prop = valor, entonces no hay razón para buscar, y este atributo (prop) se agregará directamente a este objeto (este es este). Eliminar obj.prop es similar, solo elimina las propiedades del objeto en sí, y las propiedades en el prototipo permanecen intactas.
(3) Acerca de Proto
Si está leyendo la guía, aquí llamamos __proto__, que se representa en la guía como [[prototipo]]. Ambos soportes son importantes porque hay otra propiedad llamada prototipo.
2. Object.create, object.getPrototypeOf
__proto__ es una propiedad no estándar proporcionada por Chrome/Firefox y permanece invisible en otros navegadores.
Todos los navegadores modernos, excepto Opera (es decir, 9), admiten dos funciones estándar para manejar problemas de prototipo:
Object.ceate (Prop [, Props])
Cree un objeto vacío con el Proto dado:
var animal = {come: true} rabbit = object.create (animal) alerta (rabbit.eats) // verdaderoEl código anterior crea un objeto de conejo vacío y el prototipo se establece en animal
Después de crear el objeto de conejo, podemos agregarle propiedades:
var animal = {come: true} rabbit = object.create (animal) rabbit.jumps = verdaderoEl segundo parámetro de la función Object.Creat es opcional, lo que permite que las propiedades se establezcan como objetos nuevos. Esto se omite debido a la herencia de nuestra relación.
(1) Object.getPrototypeOf (OBJ)
Devuelve el valor de OBJ .__ Proto__. Esta función es estándar y se puede usar en navegadores que no pueden acceder directamente al atributo __proto__.
var animal = {come: true} rabbit = object.create (animal) alerta (object.getPrototypeOf (conejo) === animal) // trueLos navegadores modernos permiten la lectura de los valores de atributos __proto__, pero no se pueden establecer.
3. El prototipo
Hay algunas buenas formas de navegador cruzado de establecer el atributo __proto__, que utilizará funciones de constructor. ¡recordar! Cualquier función crea un objeto a través de la nueva palabra clave.
Una castaña:
function rabbit (name) {this.name = name} var rabbit = new Rabbit ('John') alerta (rabbit.name) // JohnLa nueva operación establece las propiedades del prototipo en la propiedad __proto__ del objeto de conejo.
Echemos un vistazo a su principio, por ejemplo, un nuevo objeto de conejo, que hereda el animal.
var animal = {come: true} function rabbit (name) {this.name = name} rabbit.prototype = animalvar rabbit = new rabbit ('John') alerta (rabbit.eats) // true, porque conejo .__ proto__ == animalRabbit.prototype = animal literal significa: establecer __proto__ = animal para todos los objetos creados por nuevo conejo
4. Objeto de navegador cruzado. CREATE (Proto)
Object.Create (PROP) La función es poderosa porque permite la herencia directa de un objeto dado. Se puede simular mediante el siguiente código:
function Herherit (proto) {function f () {} F.Prototype = Proto return New F}heredar (animal) es exactamente equivalente a objeto. Cree (animal), devuelve un objeto vacío y objeto .__ proto__ = animal.
Una castaña:
var animal = {come: true} var rabbit = herhherit (animal) alerta (rabbit.eats) // treeLert (rabbit.hasownproperty ('eats')) // falso, de prototipoEchemos un vistazo a cuál es su principio:
function herhherit (proto) {function f () {} // (1) f.prototype = proto // (2) return nuevo f () // (3)}(1) Se creó una nueva función, y la función no estableció ningún atributo a esto, por lo que `New F` creará un objeto vacío.
(2) `F.Prototype` está configurado en Proto
(3) `new` f crea un objeto vacío, el` __proto__ = f.prototype` del objeto
(4) Bingo! Obtenemos un objeto vacío que herede `proto`
Esta función se usa ampliamente en varias bibliotecas y marcos.
Su función acepta un objeto con opciones
/ * Las opciones contienen configuración del menú: ancho, altura etc */menú de funciones (opciones) {// ...} Desea establecer ciertas opciones menú (opciones) {options.width = options.width || 300 // Establecer valor predeterminado // ...}. . . Pero cambiar el valor del parámetro puede producir algunos resultados incorrectos, ya que las opciones pueden usarse en el código externo. Una solución es clonar el objeto Opciones, copiar todos los atributos en un nuevo objeto y modificarlo en el nuevo objeto.
¿Cómo resolver este problema con la herencia? Las opciones de PS pueden agregar configuración, pero no se pueden eliminar.
Solución
Puede heredar opciones y modificar o agregar nuevas propiedades en su subclase.
function hereT (proto) {function f () {} f.prototype = proto return nuevo f} menú de funciones (opciones) {var opts = herhherit (options) opts.width = opts.width || 300 // ...}Todas las operaciones solo son válidas en subobjetos. Cuando finaliza el método de menú, el código externo aún puede usar objetos de opciones sin modificar. Eliminar la operación es muy importante aquí. Si el ancho es una propiedad en un prototipo, Eliminar Opts.Width no tendrá ningún efecto
5. HaswnProperty
Todos los objetos tienen la función de Property de Haswn, que puede usarse para detectar si una propiedad es en sí misma o un prototipo.
Una castaña:
function rabbit (name) {this.name = name} rabbit.prototype = {eats: true} var rabbit = new rabbit ('John') alerta (rabbit.hasownproperty ('eats')) // falso, en prototypeAlert (rabbit.hasownproperty ('nombre') // verdadero, en objeto, en objetos6. Logros con/sin propiedades heredadas
para ... en bucle sale todas las propiedades de un objeto, incluidos los propios y el prototipo.
function rabbit (name) {this.name = name} rabbit.prototype = {eats: true} var rabbit = new rabbit ('John') para (var p en conejo) {alerta (p + "=" + conejo [p]) // sale tanto "nombre" como "come"}Use aSownProperty para filtrar las propiedades del objeto:
function rabbit (name) {this.name = name} rabbit.prototype = {eats: true} var rabbit = new rabbit ('John') for (var p en rabbit) {if (! rabbit.hasownproperty (p)) continúa // filtrar "come" alerta (p + "=" + rabbit [p]) // solo salidas "}}}}}}7. Resumen
JavaScript implementa la herencia a través de un atributo especial Proto
Al acceder a las propiedades de un objeto, si el intérprete no puede encontrarlo en el objeto, continuará buscando las propiedades de la función, esto apunta al objeto, no a su prototipo.
Asignar obj.prop = valor, eliminar obj.prop
Gestionar Proto:
Chrome y Firefox pueden acceder directamente al atributo __proto__ del objeto. La mayoría de los navegadores modernos admiten acceso de solo lectura usando Object.getPrototypeOf (OBJ).
Object.Create (Proto) puede generar objetos infantiles vacíos con el Proto dado, o lograr la misma función a través del siguiente código:
function Herherit (proto) {function f () {} f.prototype = proto return New f ()}Otros métodos:
para ... en salidas de bucle todas las propiedades de un objeto (incluidos los propios y el prototipo) y la cadena prototipo del objeto.
Si una propiedad de propiedad pertenece al objeto obj, entonces obj.hasownproperty (prop) devuelve verdadero, de lo contrario falso.