objetos - Extender un objeto en Javascript
recorrer array de objetos javascript (14)
Enfoque diferente: Object.create
Por respuesta de @osahyoun, encuentro lo siguiente como una forma mejor y más eficiente de ''heredar'' del objeto prototipo de la persona:
function Person(name){
this.name = name;
this.type = ''human'';
}
Person.prototype.info = function(){
console.log("Name:", this.name, "Type:", this.type);
}
function Robot(name){
Person.call(this, name)
this.type = ''robot'';
}
// Set Robot''s prototype to Person''s prototype
Robot.prototype = Object.create(Person.prototype);
// Set constructor back to Robot
Robot.prototype.constructor = Robot;
person = new Person("Bob");
robot = new Robot("Boutros");
person.info(); // Name: Bob Type: human
robot.info(); // Name: Boutros Type: robot
Ahora, usando Object.create , Person.prototype.constructor !== Robot
Verifique también la documentación de Object.create .
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 que haga.
He visto a varias personas en Internet usar un método llamado extender en el 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 oído 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.
Mundo sin la palabra clave "nueva".
Y una sintaxis más simple con Object.create ().
Estoy en el campo que cree que Javascript debería intentar vivir sin "nuevo". Es un lenguaje sin clases, no necesita constructores. Simplemente crea Objetos y luego los extiende o transforma. De acuerdo, hay trampas, pero esto es mucho más poderoso y simple:
// base `Person` prototype
var Person = {
name : '''',
age : 22,
type : ''human'',
greet: function() {
console.log(''Hi, my name is '' + this.name + '' and I am a '' + this.type + ''.'' );
}
};
// create an instance of `Person`:
var skywalker = Object.create(Person);
skywalker.name = ''Anakin Skywalker'';
skywalker.greet(); // ''Hi, my name is Anakin Skywalker and I am a human.''
Extender el prototipo base
// create a `Robot` prototype by extending the `Person` prototype:
var Robot = Object.create(Person);
Robot.type = ''robot'';
Robot.variant = ''''; // add properties for Robot prototype
// Robots speak in binaries, so we need a different greet function:
Robot.greet = function() { //some function to convert strings to binary }
Un nivel más profundo
// create a new instance `Robot`
var Astromech = Object.create(Robot);
Astromech.variant = ''astromech'';
var r2d2 = Object.create(Astromech);
r2d2.name = ''R2D2'';
r2d2.greet(); // ''0000111010101011100111....''
// morphing the `Robot` object doesn''t affect `Person` prototypes
skywalker.greet(); // ''Hi, my name is Anakin Skywalker and I am a human.''
Otras lecturas
** Actualización 22 Ene 17. Incluye ES6 Object.assign ().
Como puede ver, la tarea requiere múltiples declaraciones. Con ES6, puede usar el método #assign para acortar las asignaciones. (Para que polyfill se use en navegadores más antiguos, vea MDN en ES6 ).
//instead of this
var Robot = Object.create(Person);
Robot.name = "Robot";
Robot.madeOf = "metal";
Robot.powerConsumption_kW = 5;
//you can do this
var Robot = Object.create(Person);
Object.assign(Robot, {
name = "Robot",
madeOf: "metal",
powerConsumption_kWh: 5,
fullCharge_kWh = 10,
currentCharge_kWh = 5
});
//attach some methods unique to Robot prototype.
Robot.charge = function(kWh) {
var self = this;
this.currentCharge_kWh = Math.min(self.fullCharge_kWh, self.currentCharge_kWh + kWh);
var percentageCharged = this.currentCharge_kWh / this.fullCharge_kWh * 100;
console.log(this.name + (percentageCharged === 100) ? '' is fully charged.'' : '' is '' + percentageCharged +''% charged.'');
};
Robot.charge(5); // outputs "Robot is fully charged."
//you can also use Object.create()''s second argument a.k.a propertiesObject,
//which I find to be a little too lengthy. The only reason to use it over #assign is if you need more control over the values i.e writability/configurability etc...
var Robot = Object.create(Person, {
madeOf: {
value: "metal",
writable: true,
configurable: true,
enumerable: true
},
powerConsumption: {
value: "5kWh",
writable: true,
configurable: true,
enumerable: true
}
});
Hay trampas en este patrón que es probable que tropiecen con los programadores "entrenados en clásicos". No obstante, creo que este patrón es mucho más legible.
En la mayoría de los proyectos hay algunas implementaciones de extensión de objetos: guión bajo, jquery, lodash: extender .
También hay una implementación pura de javascript, que es parte de ECMAscript 6: Object.assign : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
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 forma de aprender mirando su código fuente. La página de código fuente anotada es bastante útil.
Esto hará que extender sus propiedades cree un nuevo Objeto con los prototipos de parámetros de objeto sin alterar el objeto pasado.
function extend(object) {
if (object === null)
throw TypeError;
if (typeof object !== "object" && typeof object !== "function")
throw TypeError;
if (Object.create)
return Object.create(object);
function f() {}
;
f.prototype = p;
return new f();
}
Pero si desea extender su Objeto sin modificar los parámetros, puede agregar extendProperty a su objeto.
var Person{
//some code
extend: extendProperty
}
//Enforce type checking an Error report as you wish
function extendProperty(object) {
if ((object !== null && (typeof object === "object" || typeof object === "function"))){
for (var prop in object) {
if (object.hasOwnProperty(prop))
this[prop] = object[prop];
}
}else{
throw TypeError; //Not an object
}
}
La creación de prototipos es una buena manera, pero el prototipo es bastante peligroso a veces y puede dar lugar a errores. Prefiero encapsular esto en un objeto base, como lo hace Ember.js en Ember.Object.extend y Ember.Object.reopen. Eso es mucho más seguro de usar.
Creé una idea de cómo configurar algo similar a lo que usa Ember.Object.
Aquí está el enlace: https://gist.github.com/WebCloud/cbfe2d848c80d4b9e9bd
Mozilla ''anuncia'' 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 (Harmony).
class Square extends Polygon {
constructor(length) {
// Here, it calls the parent class'' constructor with lengths
// provided for the Polygon''s width and height
super(length, length);
// Note: In derived classes, super() must be called before you
// can use ''this''. Leaving this out will cause a reference error.
this.name = ''Square'';
}
get area() {
return this.height * this.width;
}
set area(value) {
this.area = value; }
}
Esta tecnología está disponible en Gecko (Google Chrome / Firefox) - 03/2015 construcciones nocturnas.
Si aún no ha descubierto una forma, use la propiedad asociativa de los objetos de JavaScript para agregar una función de extensión al Object.prototype
como se muestra a continuación.
Object.prototype.extend = function(obj) {
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
this[i] = obj[i];
}
}
};
Puede usar esta función como se muestra a continuación.
var o = { member: "some member" };
var x = { extension: "some extension" };
o.extend(x);
Simplemente puede hacerlo usando:
Object.prototype.extend = function(object) {
// loop through object
for (var i in object) {
// check if the extended object has that property
if (object.hasOwnProperty(i)) {
// mow check if the child is also and object so we go through it recursively
if (typeof this[i] == "object" && this.hasOwnProperty(i) && this[i] != null) {
this[i].extend(object[i]);
} else {
this[i] = object[i];
}
}
}
return this;
};
actualización: comprobé
this[i] != null
ya quenull
es un objeto
Entonces úsalo como:
var options = {
foo: ''bar'',
baz: ''dar''
}
var defaults = {
foo: false,
baz: ''car'',
nat: 0
}
defaults.extend(options);
Este bien resulta en:
// defaults will now be
{
foo: ''bar'',
baz: ''dar'',
nat: 0
}
Y un año más tarde, puedo decirles que hay otra buena respuesta.
Si no le gusta la forma en que funciona la creación de prototipos para ampliar los objetos / clases, consulte esto: https://github.com/haroldiedema/joii
Código de posibilidades de ejemplo rápido (y muchos más):
var Person = Class({
username: ''John'',
role: ''Employee'',
__construct: function(name, role) {
this.username = name;
this.role = role;
},
getNameAndRole: function() {
return this.username + '' - '' + this.role;
}
});
var Manager = Class({ extends: Person }, {
__construct: function(name)
{
this.super(''__construct'', name, ''Manager'');
}
});
var m = new Manager(''John'');
console.log(m.getNameAndRole()); // Prints: "John - Manager"
Editar :
Antes de usar el código, verifique los comentarios del usuario2491400 que informa sobre los efectos secundarios de simplemente asignar al prototype
.
Respuesta original:
Desea ''heredar'' del objeto prototipo de la persona:
var Person = function(name){
this.name = name;
this.type = ''human'';
}
Person.prototype.info = function(){
console.log("Name:", this.name, "Type:", this.type);
}
var Robot = function(name){
Person.apply(this,arguments)
this.name = name;
this.type = ''robot'';
}
Robot.prototype = Person.prototype; // Set prototype to Person''s
Robot.prototype.constructor = Robot; // Set constructor back to Robot
person = new Person("Bob");
robot = new Robot("Boutros");
person.info();
// Name: Bob Type: human
robot.info();
// Name: Boutros Type: robot
En ES6 , hay Object.assign
para copiar los valores de las propiedades. Use {}
como primer parámetro si no desea modificar el objeto objetivo (se pasa el primer parámetro).
var resultObj = Object.assign({},Obj1,Obj2);
Para más detalles ver enlace,
En caso de que necesite un Polyfill para ES5 , el enlace también lo ofrecerá. :)
Function.prototype.extends=function(ParentClass) {
this.prototype = new ParentClass();
this.prototype.constructor = this;
}
Entonces:
function Person() {
this.name = "anonym"
this.skills = ["abc"];
}
Person.prototype.profile = function() {
return this.skills.length // 1
};
function Student() {} //well extends fom Person Class
Student.extends(Person)
var s1 = new Student();
s1.skills.push("")
s1.profile() // 2
Actualización 01/2017:
Por favor, ignore mi respuesta de 2015 ya que ahora Javascript admite la extends
palabra clave desde ES6 (Ecmasctipt6)
- ES6:
class Person {
constructor() {
this.name = "anonym"
this.skills = ["abc"];
}
profile() {
return this.skills.length // 1
}
}
Person.MAX_SKILLS = 10;
class Student extends Person {
} //well extends from Person Class
//-----------------
var s1 = new Student();
s1.skills.push("")
s1.profile() // 2
- ES7:
class Person {
static MAX_SKILLS = 10;
name = "anonym"
skills = ["abc"];
profile() {
return this.skills.length // 1
}
}
class Student extends Person {
} //well extends from Person Class
//-----------------
var s1 = new Student();
s1.skills.push("")
s1.profile() // 2
No es necesario usar ninguna biblioteca externa para extender
En JavaScript, todo es un objeto (a excepción de los tres tipos de datos primitivos, e incluso se envuelven automáticamente con objetos cuando es necesario). Además, todos los objetos son mutables.
Persona de clase en JavaScript
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype = {
getName: function() {
return this.name;
},
getAge: function() {
return this.age;
}
}
/* Instantiate the class. */
var alice = new Person(''Alice'', 93);
var bill = new Person(''Bill'', 30);
Modificar una instancia / objeto específico .
alice.displayGreeting = function()
{
alert(this.getGreeting());
}
Modificar la clase
Person.prototype.getGreeting = function()
{
return ''Hi '' + this.getName() + ''!'';
};
O simplemente diga: extienden JSON y OBJECT ambos son iguales
var k = {
name : ''jack'',
age : 30
}
k.gender = ''male''; /*object or json k got extended with new property gender*/
gracias a ross harmes, dustin diaz