Vengo a Javascript desde un fondo en Python y Smalltalk, y aprecio el linage de Self y Lisp en el idioma. Con ECMAScript5, quería probar mi mano en OO prototípico sin el nuevo operador.Prototypal OO con constructores Object.create y named
Restricciones:
- opcional operador new para crear clases cadena
- prototipo debe ser correcta para instanceof
- constructores llevan el nombre de WebInspector compatibilidad de depuración
- alloc init()() Secuencia de creación similares. Objective-C y Python
Aquí está mi intento de la implementación para cumplir t él criterios:
function subclass(Class, Base) {
"use strict";
function create(self, args) {
if (!(self instanceof this))
self = Object.create(this.prototype);
var init = self.__init__;
return init ? init.apply(self, args) : self;
}
if (Base instanceof Function) Base = Base.prototype;
else if (Base===undefined) Base = Object.prototype;
Class.prototype = Object.create(Base);
Class.prototype.constructor = Class;
Class.create = create;
Class.define = function define(name, fn) { return Class.prototype[name] = fn; };
Class.define('__name__', Class.name);
return Class;
}
Y parece que funciona de una forma sencilla maqueta:
function Family(){return Family.create(this, arguments)}
subclass(Family, Object);
Family.define('__init__', function __init__(n){this.name=n; return this;});
function Tribe(){return Tribe.create(this, arguments)}
subclass(Tribe, Family);
function Genus(){return Genus.create(this, arguments)}
subclass(Genus, Tribe);
function Species(){return Species.create(this, arguments)}
subclass(Species, Genus);
Utilización de la clase como una función de la fábrica:
var dog = Species('dog');
console.assert(dog instanceof Object);
console.assert(dog instanceof Family);
console.assert(dog instanceof Tribe);
console.assert(dog instanceof Genus);
console.assert(dog instanceof Species);
o utilizar el nuevo operador:
var cat = new Species('cat');
console.assert(cat instanceof Object);
console.assert(cat instanceof Family);
console.assert(cat instanceof Tribe);
console.assert(cat instanceof Genus);
console.assert(cat instanceof Species);
console.assert(Object.getPrototypeOf(dog) === Object.getPrototypeOf(cat))
¿Se me pasó por alto? características de Prototypal OO en mi implementación? ¿Hay convenciones o interacciones de JavaScript para las que debería hacer cambios? En resumen, ¿qué son los "gotcha" aquí y hay mejoras obvias que hacer?
Yo quería ser DRYer con las definiciones de constructor, pero encontré que la propiedad del nombre de una función no es escribible, y eso es lo que admite los nombres de los objetos del Inspector WebKit. Pude construir una evaluación para lograr lo que quería, pero ... asco.
wow, nunca he visto usando javascript esta manera ... –
eval es peligroso si al procesar datas más "no confiables", pero no veo por qué no se debería utilizar eval, de hecho, cuando se hace esto [ astring] está utilizando algún tipo de evaluación, ya que no hay matrices asociativas en js. – mpm
@camus sí, e incluso usé una expresión regular '/ \ w + /' para asegurarme de que solo era un nombre de método válido. Pero parece que usar un martillo para instalar una tachuela: sería mucho más elegante si se le permitiera establecer la propiedad del nombre de una función. Javascript es un lenguaje prototipo, después de todo ... –