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?Buen ejemplo de la herencia basada en prototipos de JavaScript
Respuesta
Douglas Crockford tiene una buena página en JavaScript Prototypal Inheritance:
haceCinco años escribí Classical Inheritance 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. de
Dean Edward Base.js, Mootools's Class o John Resig's Simple Inheritance obras son maneras de hacer classical inheritance en JavaScript.
¿Por qué no simplemente 'newObj = Object.create (oldObj);' si lo quiere sin clases? De lo contrario, reemplace con 'oldObj' con el objeto prototipo de la función de constructor ¿debería funcionar? – Cyker
Se apreciaría un ejemplo de código. – JedatKinports
me gustaría echar un vistazo a YUI, y al Base
biblioteca de Dean Edward: http://dean.edwards.name/weblog/2006/03/base/
Para YUI puede tomar un rápido vistazo a la lang module, 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.
+1 para Dean's Base.js –
YUI 2 ha quedado obsoleto a partir de 2011, por lo que el enlace a 'lang' está semi-roto. ¿Alguien se preocupa por arreglarlo para YUI 3? – ack
También está la biblioteca Ajax de ASP.NET de Microsoft, http://www.asp.net/ajax/.
También hay muchos artículos buenos de MSDN, incluidos Create Advanced Web Applications With Object-Oriented Techniques.
¡Es un buen artículo, gracias! –
Sugiero mirar Class.create PrototypeJS':
Línea 83 @http://prototypejs.org/assets/2009/8/31/prototype.js
Los mejores ejemplos que he visto están en Douglas Crockford JavaScript: 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.
responsable? eso suena casi como "culpable de" :) –
@Roland Creo que JSON es un buen formato no detallado para almacenar datos. Definitivamente no lo inventó, el formato estaba ahí para la configuración de configuración en Steam en 2002 –
Chris S, creo que también - Más y más a menudo desearía haber omitido todos los XML como formato de intercambio y seguir adelante el JSON de inmediato. –
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 va a volver a crear el objeto cada vez que cree una. Otro enfoque es declarar sus objetos en la pila prototipo, así:
// 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 un pequeño inconveniente cuando se trata de la 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.
Tenga en cuenta que en testOne 'privateVariable' es simplemente una variable en el ámbito de [IIFE] (http://benalman.com/news/2010/11/immediately-invoked-function-expression/), y se comparte en todas las instancias, por lo que no debe almacenar datos específicos de la instancia en él. (en testTwo es específico de la instancia, ya que cada llamada a testTwo() crea un nuevo alcance, por instancia) – shesek
He votado a favor porque mostraste el otro enfoque y por qué no usarlo porque hace copias – Murphy316
El problema de volver a crear el objeto siempre se debe principalmente a los métodos que se están recreando para cada nuevo objeto. Sin embargo, podemos mitigar el problema definiendo el método en 'Dog.prototype'. Entonces, en lugar de usar 'this.bark = function() {...}', podemos hacer 'Dot.prototype.bark = function() {...}' fuera de la función 'Dog'. (Consulte más detalles en [esta respuesta] (http://stackoverflow.com/a/1598077/3522482)) –
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);
Quizás agregar este enlace con su respuesta podría completar la imagen aún más: https://developer.mozilla.org/ en/docs/Web/JavaScript/Reference/Global_Objects/Object/create – Dynom
Hay un fragmento JavaScript Prototype-based Inheritance con implementaciones específicas de la versión ECMAScript.Elegirá automáticamente qué usar entre las implementaciones ES6, ES5 y ES3 de acuerdo con el tiempo de ejecución actual.
Este es el ejemplo más claro que he encontrado, del libro de Mixu Nodo (http://book.mixu.net/node/ch6.html):
estoy a favor de la composición sobre la herencia:
Composición - 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 la funcionalidad de sus clases principales. Si debe tener herencia, use el antiguo JS
Si debe implementar la herencia, al menos evite el uso de otra implementación no estándar/función mágica. Aquí es cómo puede implementar un facsímil razonable de la herencia en el más puro ES3 (siempre a medida que siga la regla de no definir las propiedades de los 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 estándar, Javascript comprensible y tiene la funcionalidad que busca principalmente: constructores encadenables y la capacidad de llamar a los métodos de la superclase.
ES6 class
y extends
ES6 class
y extends
son sólo azúcar sintaxis para antes posible manipulación cadena de prototipo, y así podría decirse que la configuración más canónica.
En primer lugar aprender más acerca de la cadena de prototipos y la búsqueda de .
propiedad en: https://stackoverflow.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://stackoverflow.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 y 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
Tu avatar es un hombre tan impresionante –
@CharlesChow gracias! –
- 1. ¿ExpandoObject de C# 4.0 admite la herencia basada en prototipos?
- 2. JavaScript herencia funcional con prototipos
- 3. herencia de prototipos en PHP (como en JavaScript)
- 4. Problema de herencia de Javascript al usar prototipos - instancias sobreescritas :(
- 5. buen ejemplo de OO JS?
- 6. ¿Por qué se implementó JavaScript usando herencia de prototipos?
- 7. ¿Cómo hago JavaScript Prototype Herencia (cadena de prototipos)
- 8. Necesita un buen ejemplo: Google Calendar API en Javascript
- 9. ¿Por qué utilizar la herencia de estilo OOP basada en clase en javascript?
- 10. Prototipos en JavaScript
- 11. ¿Cuál será un buen método minimalista de herencia de Javascript?
- 12. Herencia de estilo basada en XAML diferente
- 13. Ejemplo simple de un buen estilo de programación de Javascript?
- 14. ¿Qué son prototipos en JavaScript?
- 15. La herencia de javascript
- 16. ¿Buen ejemplo de usar libpurple?
- 17. Pobre ejemplo de herencia en C#
- 18. de la herencia de prototipo en JavaScript
- 19. Herencia de clase en Javascript
- 20. Idea de herencia de Javascript (parte 2)
- 21. ¿Los prototipos son malos en JavaScript?
- 22. Tratando de entender el punto de los prototipos en JavaScript
- 23. ¿Hay un buen ejemplo de UITabBarController?
- 24. Buen ejemplo de extensiones reactivas Use
- 25. un buen ejemplo de las mejores prácticas
- 26. ¿Algún buen ejemplo de programación usando libssl?
- 27. Mejora de la herencia de JavaScript simple
- 28. Orientación de objetos basada en prototipos. ¿Lo bueno, lo malo y lo feo?
- 29. Corrección de la herencia de JavaScript
- 30. Ejemplo simple de herencia C++, ¿qué ocurre?
¿Recibió la oportunidad de comprobar que la biblioteca Base? Realmente es lindo, y bastante pequeño. Si te gusta, considera marcar mi respuesta como la respuesta. TIA, Roland. –
Supongo que estoy en el mismo barco que tú. También quiero aprender un poco sobre este lenguaje prototípico, no estar restringido solo a los marcos de oop o similares, incluso si son geniales y todo, tenemos que aprender, ¿no? No solo un marco de trabajo hace eso por mí, incluso si lo voy a usar. Pero aprende a crear cosas nuevas en nuevos idiomas con nuevas formas, piensa fuera de la caja. Me gusta tu estilo. Voy a intentar ayudarme y tal vez ayudarte. Tan pronto como encuentre algo, se lo haré saber. –