recorrer objetos objeto lista ejemplos definicion crear clases array agregar javascript prototype constructor

objetos - prototype javascript ejemplos



¿Cuál es el significado de la propiedad del constructor de Javascript? (5)

Intentando doblar por la cabeza alrededor de Javascript toma OO ... y, como muchos otros, se encuentra con la confusión sobre la propiedad del constructor . En particular, la importancia de la propiedad del constructor , ya que no puedo hacer que tenga ningún efecto. P.ej:

function Foo(age) { this.age = age; } function Bar() { this.name = "baz"; } Bar.prototype = new Foo(42); var b = new Bar; alert(b.constructor); // "Foo". That''s OK because we inherit `Foo`''s prototype. alert(b.name); // "baz". Shows that Bar() was called as constructor. alert(b.age); // "42", inherited from `Foo`.

En el ejemplo anterior, el objeto b parece haber llamado al constructor derecho ( Bar ), y hereda la propiedad de edad de Foo . Entonces, ¿por qué muchas personas sugieren esto como un paso necesario?

Bar.prototype.constructor = Bar;

Claramente, se llamó al constructor de Bar correcto al construir b , entonces, ¿qué impacto tiene esta propiedad prototipo? Tengo curiosidad por saber qué diferencia práctica realmente tiene hacer que la propiedad del constructor se establezca "correctamente", ya que no veo que tenga ningún efecto sobre qué constructor se llama realmente después de que se crea un objeto.


El primer paso es entender de qué se tratan el constructor y el prototype . No es difícil, pero hay que abandonar la "herencia" en el sentido clásico.

El constructor

La propiedad del constructor no causa ningún efecto particular en su programa, excepto que puede verlo para ver qué función se utilizó junto con el operador new para crear su objeto. Si escribió new Bar() , será Bar y habrá escrito new Foo , será Foo .

El Prototipo

La propiedad prototype se utiliza para la búsqueda en caso de que el objeto en cuestión no tenga la propiedad solicitada. Si escribe x.attr , JavaScript intentará encontrar attr entre los atributos de x . Si no puede encontrarlo, se verá en x.__proto__ . Si no está allí tampoco, se verá en x.__proto__.__proto__ y así sucesivamente, siempre que __proto__ esté definido.

Entonces, ¿qué es __proto__ y qué tiene que ver con el prototype ? En pocas palabras, el prototype es para "tipos", mientras que __proto__ es para "instancias". (Lo digo con comillas porque en realidad no hay ninguna diferencia entre tipos e instancias). Cuando escribe x = new MyType() , lo que sucede (entre otras cosas) es que x.__proto___ se establece en MyType.prototype .

La pregunta

Ahora, lo anterior debe ser todo lo que necesita para derivar lo que su propio ejemplo significa, pero para tratar de responder su pregunta real; "¿Por qué escribir algo así como"?

Bar.prototype.constructor = Bar;

Personalmente, nunca lo he visto y me parece un poco tonto, pero en el contexto que has dado significará que el objeto Bar.prototype (creado mediante el uso de new Foo(42) ) se posarán como han sido creados por Bar en lugar de Foo . Supongo que la idea es hacer algo similar a los lenguajes C ++ / Java / C # donde una búsqueda de tipo (la propiedad del constructor ) siempre producirá el tipo más específico en lugar del tipo del objeto más genérico que está más arriba en el prototipo- cadena.

Mi consejo: no pienses mucho sobre "herencia" en JavaScript. Los conceptos de interfaces y mixins tienen más sentido. Y no verifique los objetos para sus tipos. Verifique las propiedades requeridas en su lugar ("si camina como un pato y grazna como un pato, es un pato").

Intentando forzar a JavaScript en un modelo de herencia clásico, cuando todo lo que tiene es el prototipo de mecanismo descrito anteriormente, es lo que causa la confusión. Las muchas personas que sugirieron configurar manualmente la propiedad del constructor probablemente trataron de hacer exactamente eso. Las abstracciones son buenas, pero esta asignación manual de la propiedad del constructor no es un uso muy idiomático de JavaScript.


La propiedad del constructor hace absolutamente ninguna diferencia práctica a nada internamente. Es solo de utilidad si su código lo usa explícitamente. Por ejemplo, puede decidir que necesita que cada uno de sus objetos tenga una referencia a la función constructora real que lo creó; de ser así, deberá configurar la propiedad del constructor explícita cuando configure la herencia asignando un objeto a la propiedad del prototype la función del constructor, como en su ejemplo.


La propiedad del constructor apunta al constructor que se usó para crear la instancia del objeto. Si escribió ''new Bar ()'' será ''Bar'' y habrá escrito ''new Foo ()'' será ''Foo''.

Pero si establece el prototipo sin configurar el constructor, obtendrá algo como esto:

function Foo(age) { this.age = age; } function Bar() { this.name = "baz"; } Bar.prototype = new Foo(42); var one = new Bar(); console.log(one.constructor); // ''Foo'' var two = new Foo(); console.log(two.constructor); // ''Foo''

Para configurar el constructor en realidad para el constructor que se usó para crear el objeto, necesitamos establecer el constructor también al configurar el prototipo de la siguiente manera:

function Foo(age) { this.age = age; } function Bar() { this.name = "baz"; } Bar.prototype = new Foo(42); Bar.prototype.constructor = Bar; var one = new Bar(); console.log(one.constructor); // ''Bar'' var two = new Foo(); console.log(two.constructor); // ''Foo''


Uno de los casos de uso en los que desea que la propiedad prototype.constructor sobreviva a la reasignación de propiedades del prototype es cuando define un método en el prototype que produce nuevas instancias del mismo tipo que la instancia determinada. Ejemplo:

function Car() { } Car.prototype.orderOneLikeThis = function() { // Clone producing function return new this.constructor(); } Car.prototype.advertise = function () { console.log("I am a generic car."); } function BMW() { } BMW.prototype = Object.create(Car.prototype); BMW.prototype.constructor = BMW; // Resetting the constructor property BMW.prototype.advertise = function () { console.log("I am BMW with lots of uber features."); } var x5 = new BMW(); var myNewToy = x5.orderOneLikeThis(); myNewToy.advertise(); // => "I am BMW ..." if `BMW.prototype.constructor = BMW;` is not // commented; "I am a generic car." otherwise.


un caso para usar constructor:

  1. esta es una de las realizaciones comunes de la herencia:

    Function.prototype.extend = function(superClass,override) { var f = new Function(); f.prototype = superClass.prototype; var p = this.prototype = new f(); p.constructor = this; this.superclass = superClass.prototype; ... };

  2. esta new f() no llamaría al constructor de superClass, así que cuando crees una subClass, tal vez necesites llamar a la superclase al principio, así:

    SubClass = function() { SubClass.superClass.constructor.call(this); };

entonces la propiedad del constructor tiene sentido aquí.