En resumen:
new something2() instanceof something2 === false
En relación con esto, si se amplía su ejemplo para utilizar la propiedad prototipo
Something.prototype.method = function() { };
something2.prototype.method = function() { };
se encuentra que el prototipo no se hereda en este último caso:
typeof (new Something()).method === "function"
type (new something2()).method === "undefined"
The rea La respuesta es que estás recurriendo a una maquinaria subyacente completamente diferente.Llamar con new
invoca el mecanismo [[Construct]], que implica establecer la propiedad [[Prototype]] de acuerdo con la propiedad .prototype
del constructor.
Pero sucede algo gracioso en los pasos 8--10 del algoritmo [[Construir]]: después de configurar un nuevo objeto vacío y luego adjuntar su [[Prototipo]], hace una [[Llamar] ] al constructor real, utilizando este nuevo objeto vacío-más-prototipo como this
. Y luego, en el paso 9, si resulta que ese constructor devolvió algo --- ¡tira el objeto prototypally-bound, passed-as- this
que pasó todo el tiempo configurando!
Nota: se puede acceder de un objeto [[Prototype]] (que es diferente de la de un constructor .prototype
) con Object.getPrototypeOf
:
Object.getPrototypeOf(new Something()) === Something.prototype // steps 5 & 6
Object.getPrototypeOf(new something2()) === Object.prototype // default
para responder a algunas meta preguntas:
- No, no use mayúsculas
something2
, ya que es una función de fábrica y no un constructor. Si algo está en mayúscula, se espera que tenga semántica de constructor, p. new A() instanceof A
.
- Si le preocupa el peligro de dañar el espacio de nombres global, debe comenzar a usar strict mode, poniendo
"use strict";
en la parte superior de sus archivos. Una de las muchas y bonitas limpiezas del modo estricto es que this
está predeterminado en undefined
, no el objeto global, por lo tanto, p. llamar a un constructor sin new
dará como resultado errores en el momento en que el constructor intente adjuntar propiedades al undefined
.
- Las funciones de fábrica (también conocido como el "patrón de cierre") son en general un sustituto razonable para los constructores y las clases, siempre y cuando usted (a) no utilice la herencia; (b) no construye demasiadas instancias de ese objeto. Esto último se debe a que, en el patrón de cierre, adjunta una nueva instancia de cada método a cada objeto recién creado, lo que no es bueno para el uso de la memoria. El mayor beneficio, IMO, del patrón de cierre es la capacidad de usar "private" variables (que son good thing, y no permita que nadie le diga lo contrario: P).
Sea un poco de dudas de Sr. Crockford. Si bien tiene muchas cosas buenas que decir, sí tiene opiniones con las que no está de acuerdo. – staticsan