Actualmente me estoy transformando de Java a Javascript, y es un poco difícil para mí descubrir cómo extender los objetos de la manera que quiero.
He visto a varias personas en Internet usar un método llamado extender en objeto. El código se verá así:
var Person = {
name : 'Blank',
age : 22
}
var Robot = Person.extend({
name : 'Robo',
age : 4
)}
var robot = new Robot();
alert(robot.name); //Should return 'Robo'
¿Alguien sabe cómo hacer que esto funcione? He escuchado que necesitas escribir
Object.prototype.extend = function(...);
Pero no sé cómo hacer que este sistema funcione. Si no es posible, muéstrame otra alternativa que extienda un objeto.
extend
función, he configurado un ejemplo aquí: jsfiddle.net/k9LRdRespuestas:
Desea 'heredar' del objeto prototipo de la Persona:
fuente
Person()
llama al constructor cuando lo hacesnew Robot()
? Me parece que deberías llamar a ese constructor de clase base en lugar de hacerlothis.name = name;
en elRobot()
constructor ...Person.apply(this, arguments);
. También sería mejor usarlo enRobot.prototype = Object.create(Person.prototype);
lugar denew Person();
.Mundo sin la palabra clave "nueva".
Y una sintaxis más simple "en prosa" con Object.create ().
* Este ejemplo se actualiza para las clases de ES6.
En primer lugar, recuerde que Javascript es un lenguaje prototípico . No está basado en clases. Por lo tanto, escribir en forma prototípica expone su verdadera naturaleza y puede ser muy simple, similar a la prosa y poderoso.
TLDR;
No, no necesitas constructores, no hay
new
instanciación ( lee por qué no deberías usarnew
), nosuper
, no es gracioso__construct
. Simplemente crea objetos y luego los extiende o transforma.( Si conoce los captadores y establecedores, consulte la sección "Lecturas adicionales" para ver cómo este patrón le ofrece captadores y establecedores gratuitos de una manera que Javascript había pensado originalmente y cuán poderosos son ).
Sintaxis tipo prosa: prototipo base
De un vistazo, se ve muy legible.
Extensión, creando un descendiente de
Person
* Los términos correctos son
prototypes
, y susdescendants
. No hayclasses
y no hay necesidad de hacerloinstances
.Una forma de proporcionar una forma "predeterminada" de crear un
descendant
, es adjuntando un#create
método:Las siguientes formas tienen menor legibilidad:
Compare con el equivalente "clásico":
La legibilidad del código usando el estilo "clásico" no es tan bueno.
Clases ES6
Es cierto que algunos de estos problemas son erradicados por las clases ES6, pero aún así:
Ramificación del prototipo base
Adjunte métodos únicos para
Robot
Comprobando herencia
¡Ya tienes todo lo que necesitas! Sin constructores, sin instanciación. Prosa limpia y clara.
Otras lecturas
¡Posibilidad de escritura, configurabilidad y getters y setters gratuitos!
Para getters y setters gratuitos, o configuración adicional, puede usar el segundo argumento de Object.create () aka propertiesObject. También está disponible en # Object.defineProperty y # Object.defineProperties .
Para ilustrar cuán poderoso es esto, supongamos que queremos que todos
Robot
estén hechos estrictamente de metal (a través dewritable: false
) y estandarizar lospowerConsumption
valores (a través de getters y setters).Y todos los prototipos de
Robot
no pueden sermadeOf
otra cosa porquewritable: false
.Mixins (usando # Object.assign) - Anakin Skywalker
¿Puedes sentir a dónde va esto ...?
Darth Vader obtiene los métodos de
Robot
:Junto con otras cosas extrañas:
Bueno, si Darth Vader es hombre o máquina es realmente subjetivo:
Extra: sintaxis ligeramente más corta con # Object.assign
Con toda probabilidad, este patrón acorta su sintaxis. Pero ES6 # Object.assign puede acortar un poco más (para usar Polyfill en navegadores antiguos, consulte MDN en ES6 ).
fuente
Object.assign(Robot, {a:1}
una buena alternativa para suextend()
método? 2) ¿Cómo anular elgreet()
método para que devuelva el mismo texto, pero con "una anulación de saludo" añadida?#Object.assign
Looke como una buena alternativa. Pero el soporte del navegador es un cajero automático más bajo. 2) Utilizará la__proto__
propiedad del objeto para acceder a la función de saludo de su prototipo. luego llama a la función de saludo prototipo con el alcance del destinatario pasado. en este caso, la función era un registro de consola, por lo que no es posible "agregar". Pero con este ejemplo, creo que entiendes la deriva.skywalker.greet = function() { this.__proto__.greet.call(this); console.log('a greet override'); }
Si aún no ha descubierto una forma, use la propiedad asociativa de los objetos JavaScript para agregar una función de extensión a la
Object.prototype
que se muestra a continuación.Luego puede usar esta función como se muestra a continuación.
fuente
Enfoque diferente: Object.create
Según la respuesta de @osahyoun, encuentro lo siguiente como una forma mejor y eficiente de 'heredar' del objeto prototipo de la Persona:
Crear nuevas instancias:
Ahora, usando Object.create :
Consulte también la documentación de MDN .
fuente
name
parámetro al constructor principal, como este: jsfiddle.net/3brm0a7a/3 (la diferencia está en la línea # 8)En ES6 , puede usar el operador de propagación como
Para obtener más información, consulte el enlace, Sintaxis extendida de MDN
Vieja respuesta:
En ES6 , existe
Object.assign
para copiar valores de propiedad. Úselo{}
como primer parámetro si no desea modificar el objeto de destino (se aprobó el primer parámetro).Para más detalles ver enlace, MDN - Object.assign ()
En caso de que necesite un Polyfill para ES5 , el enlace también lo ofrece. :)
fuente
Y otro año después, puedo decirte que hay otra buena respuesta.
Si no le gusta la forma en que funciona la creación de prototipos para extenderse en objetos / clases, observe esto: https://github.com/haroldiedema/joii
Código de ejemplo rápido de posibilidades (y muchos más):
fuente
Las personas que todavía están luchando por el enfoque simple y mejor, puede usar
Spread Syntax
para extender objetos.Nota: Recuerde que la propiedad más alejada a la derecha tendrá prioridad. En este ejemplo,
person2
está en el lado derecho, pornewObj
lo que tendrá el nombre Robo .fuente
Es posible que desee considerar el uso de la biblioteca auxiliar como underscore.js , que tiene su propia implementación de
extend()
.Y también es una buena manera de aprender mirando su código fuente. La página de código fuente anotada es bastante útil.
fuente
_.extend()
funciona el trabajo de underscore.js deja bastante clara su funcionalidad: lostechies.com/chrismissal/2012/10/05/…Mozilla 'anuncia' el objeto que se extiende desde ECMAScript 6.0:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/extends
NOTA: Esta es una tecnología experimental, parte de la propuesta ECMAScript 6 (Armonía).
Esta tecnología está disponible en Gecko (Google Chrome / Firefox) - 03/2015 versiones nocturnas.
fuente
En la mayoría de los proyectos hay algunas implementaciones de extensión de objetos: subrayado, jquery, lodash: extender .
También existe una implementación de JavaScript puro, que forma parte de ECMAscript 6: Object.assign : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
fuente
Luego:
Actualización 01/2017:
Por favor, ignore mi respuesta de 2015 ya que Javascript ahora es compatible con
extends
palabras clave desde ES6 (Ecmasctipt6)- ES6:
- ES7:
fuente
new ParentClass()
antes de sobrescribir el constructor, ya ha ejecutado el constructor principal. No creo que sea un comportamiento correcto si me preguntas ...Resumen:
Javascript usa un mecanismo que se llama herencia prototípica . La herencia de prototipos se usa cuando se busca una propiedad en un objeto. Cuando estamos extendiendo propiedades en JavaScript, heredamos estas propiedades de un objeto real. Funciona de la siguiente manera:
myObj.foo
OmyObj['foo']
) el motor JS primero buscará esa propiedad en el objeto mismoCuando queremos extender desde un objeto en javascript, simplemente podemos vincular este objeto en la cadena del prototipo. Hay numerosas formas de lograr esto, describiré 2 métodos de uso común.
Ejemplos:
1)
Object.create()
Object.create()
es una función que toma un objeto como argumento y crea un nuevo objeto. El objeto que se pasó como argumento será el prototipo del objeto recién creado. Por ejemplo:2. Establecer explícitamente la propiedad del prototipo
Al crear objetos utilizando funciones de constructor, podemos establecer propiedades de agregar a su propiedad de objeto prototipo. Los objetos que se crean forman una función constructora cuando se usa la
new
palabra clave, tienen su prototipo establecido en el prototipo de la función constructora. Por ejemplo:fuente
Simplemente puede hacerlo usando:
Luego úsalo como:
Esto da como resultado:
fuente
POR FAVOR AGREGUE LA RAZÓN PARA VOTAR
No es necesario utilizar ninguna biblioteca externa para ampliar
En JavaScript, todo es un objeto (excepto los tres tipos de datos primitivos, e incluso se envuelven automáticamente con objetos cuando es necesario). Además, todos los objetos son mutables.
gracias a ross harmes, dustin diaz
fuente
Esto hará que extender sus propiedades cree un nuevo Objeto con los prototipos de parámetros del objeto sin alterar el objeto pasado.
Pero si desea extender su Objeto sin modificar sus parámetros, puede agregar extendProperty a su objeto.
fuente
La creación de prototipos es una buena manera, pero el prototipo es bastante peligroso a veces y puede provocar errores. Prefiero encapsular esto en un objeto base, como lo hace Ember.js con Ember.Object.extend y Ember.Object.reopen. Eso es mucho más seguro de usar.
Creé una idea general de cómo configurarías algo similarCreé una idea general de a lo que usa Ember.Object.
Aquí está el enlace: https://gist.github.com/WebCloud/cbfe2d848c80d4b9e9bd
fuente
Prototyping is a nice way, but prototype is quite dangerous sometimes and can lead to bugs.
¿Qué quieres decir con eso? ¿Usar la cadena de prototipos en JavaScript puede generar errores? Es como decir que usar clases en Java puede generar errores y no tiene ningún sentido.Object
el prototipo, su función podría tener el mismo nombre que una futura función de JavaScript y hacer que su código explote cuando se ejecute en el futuro. Por ejemplo, supongamos que agregó unarepeat()
funciónObject
y la llamó enString
instancias y luego su tiempo de ejecución de JavaScript se actualizó a ES6.prototype
función del lenguaje .