ejemplos create clases javascript prototypal-inheritance

create - Buen ejemplo de la herencia basada en prototipos de JavaScript



object.create javascript (10)

Como se mencionó, las películas de Douglas Crockford dan una buena explicación sobre el por qué y cubre el cómo. Pero para ponerlo en un par de líneas de JavaScript:

// Declaring our Animal object var Animal = function () { this.name = ''unknown''; this.getName = function () { return this.name; } return this; }; // Declaring our Dog object var Dog = function () { // A private variable here var private = 42; // overriding the name this.name = "Bello"; // Implementing ".bark()" this.bark = function () { return ''MEOW''; } return this; }; // Dog extends animal Dog.prototype = new Animal(); // -- Done declaring -- // Creating an instance of Dog. var dog = new Dog(); // Proving our case console.log( "Is dog an instance of Dog? ", dog instanceof Dog, "/n", "Is dog an instance of Animal? ", dog instanceof Animal, "/n", dog.bark() +"/n", // Should be: "MEOW" dog.getName() +"/n", // Should be: "Bello" dog.private +"/n" // Should be: ''undefined'' );

El problema con este enfoque, sin embargo, es que volverá a crear el objeto cada vez que crees uno. Otro enfoque es declarar sus objetos en la pila del prototipo, de esta manera:

// Defining test one, prototypal var testOne = function () {}; testOne.prototype = (function () { var me = {}, privateVariable = 42; me.someMethod = function () { return privateVariable; }; me.publicVariable = "foo bar"; me.anotherMethod = function () { return this.publicVariable; }; return me; }()); // Defining test two, function var testTwo = ​function() { var me = {}, privateVariable = 42; me.someMethod = function () { return privateVariable; }; me.publicVariable = "foo bar"; me.anotherMethod = function () { return this.publicVariable; }; return me; }; // Proving that both techniques are functionally identical var resultTestOne = new testOne(), resultTestTwo = new testTwo(); console.log( resultTestOne.someMethod(), // Should print 42 resultTestOne.publicVariable // Should print "foo bar" ); console.log( resultTestTwo.someMethod(), // Should print 42 resultTestTwo.publicVariable // Should print "foo bar" ); // Performance benchmark start var stop, start, loopCount = 1000000; // Running testOne start = (new Date()).getTime(); for (var i = loopCount; i>0; i--) { new testOne(); } stop = (new Date()).getTime(); console.log(''Test one took: ''+ Math.round(((stop/1000) - (start/1000))*1000) +'' milliseconds''); // Running testTwo start = (new Date()).getTime(); for (var i = loopCount; i>0; i--) { new testTwo(); } stop = (new Date()).getTime(); console.log(''Test two took: ''+ Math.round(((stop/1000) - (start/1000))*1000) +'' milliseconds'');

Hay una ligera desventaja cuando se trata de introspección. El dumping de TestOne dará como resultado información menos útil. También la propiedad privada "privateVariable" en "testOne" se comparte en todas las instancias, como se menciona amablemente en las respuestas de shesek.

He estado programando con lenguajes OOP durante más de 10 años, pero ahora estoy aprendiendo JavaScript y es la primera vez que encuentro herencia basada en prototipos. Tiendo a aprender más rápido estudiando un buen código. ¿Qué es un ejemplo bien escrito de una aplicación de JavaScript (o biblioteca) que utiliza correctamente la herencia prototípica? ¿Y puede describir (brevemente) cómo / dónde se usa la herencia prototípica, entonces sé por dónde empezar a leer?


Douglas Crockford tiene una buena página en JavaScript Prototypal Herencia :

Hace cinco años escribí Herencia clásica en JavaScript. Mostró que JavaScript es un lenguaje prototípico libre de clases, y que tiene suficiente poder expresivo para simular un sistema clásico. Mi estilo de programación ha evolucionado desde entonces, como cualquier buen programador debería. Aprendí a abrazar por completo el prototipalme y me liberé de los confines del modelo clásico.

La Base.js Dean Edward, la Clase de Mootools o las obras de Herencia simple de John Resig son formas de hacer herencia clásica en JavaScript.


Este es el ejemplo más claro que he encontrado, del libro Nodo de Mixu ( http://book.mixu.net/node/ch6.html ):

Yo prefiero la composición sobre la herencia:

Composición: la funcionalidad de un objeto se compone de un agregado de diferentes clases al contener instancias de otros objetos. Herencia: la funcionalidad de un objeto se compone de su propia funcionalidad más funcionalidad de sus clases principales. Si debe tener herencia, use JS antiguo normal

Si debe implementar la herencia, al menos evite usar otra función de implementación / magia no estándar. Aquí se explica cómo puede implementar un facsímil de herencia razonable en ES3 puro (siempre que siga la regla de nunca definir propiedades en prototipos):

function Animal(name) { this.name = name; }; Animal.prototype.move = function(meters) { console.log(this.name+" moved "+meters+"m."); }; function Snake() { Animal.apply(this, Array.prototype.slice.call(arguments)); }; Snake.prototype = new Animal(); Snake.prototype.move = function() { console.log("Slithering..."); Animal.prototype.move.call(this, 5); }; var sam = new Snake("Sammy the Python"); sam.move();

Esto no es lo mismo que la herencia clásica, pero es un Javascript estándar y comprensible, y tiene la funcionalidad que la gente más busca: constructores encadenables y la capacidad de invocar métodos de la superclase.


Hay un fragmento de herencia basada en el prototipo de JavaScript con implementaciones específicas de la versión de ECMAScript. Elegirá automáticamente qué usar entre las implementaciones ES6, ES5 y ES3 de acuerdo con el tiempo de ejecución actual.


Los mejores ejemplos que he visto están en JavaScript de Douglas Crockford : The Good Parts . Definitivamente vale la pena comprar para ayudarlo a obtener una vista equilibrada del idioma.

Douglas Crockford es responsable del formato JSON y trabaja en Yahoo como un gurú de JavaScript.


Me gustaría echar un vistazo a YUI , y en la biblioteca de la Base Dean Edward: http://dean.edwards.name/weblog/2006/03/base/

Para YUI puedes echar un rápido vistazo al módulo lang , esp. el método YAHOO.lang.extend. Y luego, puede explorar la fuente de algunos widgets o utilidades y ver cómo usan ese método.




class ES6 y se extends

La class ES6 y las extends son solo azúcares de sintaxis para la manipulación de cadenas de prototipos previamente posibles, y posiblemente la configuración más canónica.

Primero aprenda más sobre la cadena de prototipos y . búsqueda de propiedades en: https://.com/a/23877420/895245

Ahora vamos a deconstruir lo que sucede:

class C { constructor(i) { this.i = i } inc() { return this.i + 1 } } class D extends C { constructor(i) { super(i) } inc2() { return this.i + 2 } }

// Inheritance syntax works as expected. (new C(1)).inc() === 2 (new D(1)).inc() === 2 (new D(1)).inc2() === 3

// "Classes" are just function objects. C.constructor === Function C.__proto__ === Function.prototype D.constructor === Function // D is a function "indirectly" through the chain. D.__proto__ === C D.__proto__.__proto__ === Function.prototype

// "extends" sets up the prototype chain so that base class // lookups will work as expected var d = new D(1) d.__proto__ === D.prototype D.prototype.__proto__ === C.prototype // This is what `d.inc` actually does. d.__proto__.__proto__.inc === C.prototype.inc

// Class variables // No ES6 syntax sugar apparently: // https://.com/questions/22528967/es6-class-variable-alternatives C.c = 1 C.c === 1 // Because `D.__proto__ === C`. D.c === 1 // Nothing makes this work. d.c === undefined

Diagrama simplificado sin todos los objetos predefinidos:

__proto__ (C)<---------------(D) (d) | | | | | | | | | |prototype |prototype |__proto__ | | | | | | | | | | | +---------+ | | | | | | | | | | v v |__proto__ (D.prototype) | | | | | | | | |__proto__ | | | | | | | | +--------------+ | | | | | | | v v | (C.prototype)--->(inc) | v Function.prototype


function Shape(x, y) { this.x = x; this.y = y; } // 1. Explicitly call base (Shape) constructor from subclass (Circle) constructor passing this as the explicit receiver function Circle(x, y, r) { Shape.call(this, x, y); this.r = r; } // 2. Use Object.create to construct the subclass prototype object to avoid calling the base constructor Circle.prototype = Object.create(Shape.prototype);