Arriva a Javascript da uno sfondo in Python e Smalltalk e apprezzo la linear di Self e Lisp nella lingua. Con ECMAScript5, volevo provare la mia mano a OO prototipo senza il nuovo operatore.OO prototipo con Object.create e costruttori con nome
Vincoli:
- nuovo operatore opzionale per creare classi
- prototipo catena deve essere corretto per instanceof
- costruttori chiamato per WebInspector supporto per il debugging
- alloc() init() sequenza di creazione simili. Objective-C e Python
Ecco il mio tentativo di implementazione per soddisfare t lui criteri:
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;
}
e sembra di lavorare in un semplice mockup:
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);
Uso della classe come una funzione di fabbrica:
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 utilizzando l'operatore new:
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))
Ho trascurato necessario caratteristiche di OO prototipo nella mia implementazione? Ci sono convenzioni o interazioni Javascript per cui dovrei apportare modifiche? In sintesi, quali sono i "gotcha" qui, e ci sono miglioramenti evidenti da apportare?
Volevo essere DRYer con le definizioni del costruttore, ma ho trovato che la proprietà del nome di una funzione non è scrivibile, e questo è ciò che supporta i nomi degli oggetti di WebKit Inspector. Sono stato in grado di costruire una valutazione per realizzare ciò che volevo, ma ... schifo.
wow, non ho mai visto utilizzando JavaScript in questo modo ... –
eval è pericoloso se quando si elabora dati "non attendibili", ma non vedo il motivo per cui non si dovrebbe usare eval, infatti quando si esegue questa operazione [ astring] stai usando qualche tipo di valutazione, in quanto non ci sono array associativi in js. – mpm
@camus yes, e ho anche usato un regexp '/ \ w +/per assicurarmi che fosse solo un nome di metodo valido. Ma sembra che usare un martello per installare una virata - Sarebbe molto più elegante se fosse permesso di impostare la proprietà del nome di una funzione. Javascript è un linguaggio prototipo, dopotutto ... –