ugrás a tartalomhoz

Típusos Javascript

inf3rno · 2010. Ápr. 30. (P), 14.46

Írtam egy nagyon egyszerű kódot a JavaScript típusossá tételére, és azt nem értem, hogy ez eddig miért nem jutott másnak is eszébe.


Function.prototype.typing = function () {
    var method = this;
    var Types  = arguments;
	
    return function () {
        if (arguments.length != Types.length) {
            throw 'Eltérő a paraméter szám...';
		}
        
        for (var i = 0, l = arguments.length; i < l; ++i) {
            var param = arguments[i];
			var Class = Types[i];

            if (!(param instanceof Class)) {
				var type = typeof(param);

                if (type != 'object') {
                    if (
						type == 'string' && Class == String
                    ||
                        type == 'number' && Class == Number
                    ||
                        type == 'boolean' && Class == Boolean
                    ) {
                        continue;
                    }
                }
                
				if (param === null) {
                    continue;
                }
                
                throw 'Eltérő típus...';
            }
        }

        return method.apply(this, arguments);
    };
};

try {
    (function (a, b, c) {}).typing(String, Number, RegExp)('a', 123, /test/g);
    (function (a, b, c) {}).typing(String, Number, RegExp)('a', null, /test/g);
    (function (a, b, c) {}).typing(String, Function, RegExp)('a', function () {}, /test/g);
    alert('jó');
} catch(e) {
    alert('rossz');
}

Persze lehetne még variálni rajta, hogy ne a függvénytörzs után legyen a típus megadása, meg a natív metódusok typeof bugját lekezelje, de nyilván csak bemutatónak szántam…

 
1

Joó Ádám · 2010. Ápr. 30. (P), 18.52
Ötletes, esetleg érdemes volna továbbfejleszteni és angolul is publikálni. Használtad már valahol?
8

Még nem

inf3rno · 2010. Május. 1. (Szo), 02.37
Még nem használtam, csak nemrég jutott eszembe. Van egy projektem, amit nyár végéig befejezek, aztán a javascriptes részhez írok egy kis kódtárat. Ezzel kapcsolatban gondolkodtam azon, hogy hogyan lehetne olyan interfaceket implementálni egy osztályban, amik átfednek, szóval azonos metódusneveket használnak. Aztán ezzel kapcsolatban arra jutottam, hogyha lenne típusellenőrzés, akkor overloaddal az argumentumok típusa alapján ki lehetne választani a megfelelő interfacet és az ahhoz tartozó implementációt.

var i1=new Interface(
{
	a: new Method(String)
});

var i2=new Interface(
{
	a: new Method(Number)
});

var C=new Class(
{
	a: new Overload(
		new Method(String,function (str)
		{
			//i1-hez tartozó implementáció
		}),
		new Method(Number,function (num)
		{
			//i2-höz tartozó implementáció
		})
	);
}).Implements(i1,i2);

var c=new C();
	c.a("valami"); //i1-es implementáció hívása
	c.a(123); //i2-es implementáció hívása
Persze ez sem tökéletes megoldás az ilyen átfedésekre, csak egy ötlet volt. A típusellenőrzés megoldása meg adta magát, mert rengeteget programoztam már javascriptben.
10

A legtöbb függvénytárban

Török Gábor · 2010. Május. 3. (H), 08.31
A legtöbb függvénytárban objektumba pakolva várják a (változó számú és típusú) függvény argumentumokat, és a függvényben a kapott paramétereknek megfelelően vezérlik a logikát. A függvény komplexitását szükség szerint tervezési mintákkal egyszerűsítik. A te elképzelésed miben nyújt többet vagy miért rugalmasabb?
11

Nehéz kérdés

inf3rno · 2010. Május. 3. (H), 20.25
Nehéz kérdés, szerintem többet nyújt, de ezt nem úgy gondolom, hogy fel kéne váltani vele az eddigi megoldásokat. Inkább mint kiegészítő nyújt többet. Szóval mondjuk az objektumos paraméterező felület megmaradhat, de a paraméterek szétosztását a típusellenőrzéssel egyszerűbb megoldani. Valahogy így gondoltam:

var Request=new Class(
{
	initialize: function (config)
	{
		//...
		if (config)
		{
			this.configure(config);
		}
	},
	configure: function (config)
	{
		var iterator=new ObjectIterator();
			iterator.setContext(config);
		for (iterator.first(); iterator.hasNext(); iterator.next())
		{
			var setter=this['set'+iterator.key.capitalize()];
			if (!setter.instanceOf(Function))
			{
				throw new ArgumentsException('Invalid arguments object.');
			}
			setter.call(this,iterator.value);
		}
	}.decorate({typing: [Object]}),
	setUrl: function (url)
	{
		//...
	}.decorate({typing: [String]}),
	setMethod: function (method)
	{
		//...
	}.decorate({typing: [String]}),
	setSync: function (sync)
	{
		//...
	}.decorate({typing: [Boolean]}),
	setComplete: function (listener)
	{
		//...
	}.decorate({typing: [Function]}),
	send: function ()
	{
		//...
	}

})


new Request(
{
	url: 'test.php',
	method: 'get',
	sync: false,
	complete: Function.overload(
		function (content)
		{
			//...
		}.decorate({typing: [String]}),
		function (error)
		{
			//...
		}.decorate({typing: [Exception]})
	)
}).send();

Kicsit továbbmentem, mint a típusellenőrzés, és én összefognám ezeket a closure-os dolgokat. Nyilván ez decorator pattern, csak itt nem díszítő objektumról, hanem díszítő függvényről van szó.
Nyilván nem csak a típusellenőrzésről van szó, hanem mondjuk a prototype.js-ben fordulnak elő még ilyenek, hogy bind, delay meg hasonlók. Úgy általánosságban be lehet így állítani a scope-ot, a scope bizonyos tulajdonságait ideiglenesen átírni, amíg a függvény fut, típusellenőrzést automatizálni stb..

Pl a típusellenőrzést ki lehetne terjeszteni akár DOM objektumokra is.

$("#container *").each(Function.overload(
	function (a)
	{
		alert('Külső link: '+a.getAttribute('href'));
	}.decorate({selector: "a.external"}),
	function (a)
	{
		alert('Belső link: http://test.com/'+a.getAttribute('href'));
	}.decorate({selector: "a.internal"}),
));
Szerintem ez a forma átláthatóbb, mint if-ekkel. (Persze ezt két $ függvénnyel is meg lehet oldani.)
Leginkább a switch-eket, meg az olyan if-else kódrészeket szeretném helyettesíteni így, amikben csak a típusellenőrzésről van szó. Class.extends szimulálásánál pedig az ideiglenes scope tulajdonság átírás, ami használható, mert a this.parent az függ attól, hogy az adott függvényt melyik osztályban adtuk meg először. Nyilván annak a szülőjére vonatkozik a this.parent.

Itt például ha a this.parent a B.prototype-ra vonatkozna, akkor végtelen ciklusba kerülnénk, ezért ideiglenesen a this.parent-et át kell írni A.prototype-ba, amikor a B.initialize-t futtatja a rendszer.

var A=new Class(
{
	initialize: function ()
	{
		alert("a");
	}
});
var B=new Class(
{
	initialize: function ()
	{
		this.parent.initialize.apply(this,arguments);
		alert("b");
	}
}).Extends(A);

var C=new Class(
{

}).Extends(B);

var c=new C();
Ha úgy érzed nem kielégítő a válasz, akkor kérdezz konkrétabban légyszíves, mert most csak úgy általánosságban válaszoltam.
12

Én is csak általánosságban

Török Gábor · 2010. Május. 4. (K), 09.10
Én is csak általánosságban kérdeztem, mert hirtelen nem láttam jó felhasználási lehetőségét az ötletednek, de a dekorálással karöltve valóban érdekes. Köszönöm.
2

{ } jelek

Poetro · 2010. Ápr. 30. (P), 19.07
Épp akartam szólni a {}, de látom azóta javítva lettek.
6

Hát..

inf3rno · 2010. Május. 1. (Szo), 01.22
Hát én nem tudok semmit róla, én csak beküldtem...
3

JSLint barát változat

Poetro · 2010. Ápr. 30. (P), 21.47
Function.prototype.typing = function () {
  var method = this,
      types  = arguments;

  return function () {
    var param,
        klass,
        type,
        i,
        l = types.length;

    if (arguments.length !== l) {
      throw {
        'name'     : 'ArgumentsError',
        'toString' : Error.prototype.toString,
        'message'  : 'Supplied number of arguments do not match the ' +
                     'required number of arguments of ' + l + '.'
      };
    }

    for (i = 0; i < l; i += 1) {
      param = arguments[i];
      klass = types[i];

      if (!(param instanceof klass)) {
        type = typeof param;

        if (type !== 'object') {
          if (type === 'string' && klass === String ||
              type === 'number' && klass === Number ||
              type === 'boolean' && klass === Boolean) {
            continue;
          }
        }

        if (param === null) {
          continue;
        }

        throw new TypeError('Supplied argument type for argument ' +
                            i + ' does not match with required type.');
      }
    }

    return method.apply(this, arguments);
  };
};
9

Köszi

inf3rno · 2010. Május. 1. (Szo), 02.44
Köszi, elgondolkodtam, hogy használni fogom ezt a jsLint-et, bár inkább olyan jellegű hibáim szoktak lenni javascripttel, amik böngészőfüggőek...
4

Inkább…

presidento · 2010. Ápr. 30. (P), 23.31
A nem típusos nyelvek nem akarnak kihalni, ezek szerint a típusosságot erőltetni nem szükséges. Persze, van/lehet haszna, de szerintem leginkább a fejlesztői fázisban, nem az éles környezetben. Én valahogy így csinálnám (pszeudo kód):
Function.create = function(class1, class2, ..., func) {
	if ( DEBUG ) {
		// check things
	} else {
		return func;
	}
};

var func = Function.create(String, Number, RegExp, function (a, b, c) {});
func('a', 123, /test/g);
5

Bármilyen felülettel lehet

inf3rno · 2010. Május. 1. (Szo), 01.18
Szia!

Bármilyen felülettel meg lehet csinálni, az implementáció onnantól, hogy megvan a típusok tömbje, meg a metódus, ugyanaz lesz.

pl:

var Method=function (Types,method)
{
	return function ()
	{
		if (arguments.length!=Types.length)
		{
			throw "Eltérő a paraméter szám...";
		}
		for (var i=0,l=arguments.length; i<l; ++i)
		{
			var param=arguments[i];
			var Class=Types[i];
			if (!(param instanceof Class))
			{
				var type=typeof(param);
				if (type!="object")
				{
					if (
						type=="string" && Class==String
					||
						type=="number" && Class==Number
					||
						type=="boolean" && Class==Boolean
					)
					{
						continue;
					}
				}
				if (param===null)
				{
					continue;
				}
				throw "Eltérő típus...";
			}
		}
		return method.apply(this,arguments);
	};
};

new Method([String,Number,RegExp],function (a,b,c){});
Amit még érdemes lenne megcsinálni az az overloading. Szóval hogy egy metódusra több implementációt adok meg típusokkal, aztán a rendszer dönti el a bejövő paraméterek típusa alapján, hogy melyik implementációt használja.

Csak nagyon egyszerűen valami ilyesmire gondolok:

var Data=new Class(
{
	print: new Overload(
		new Method([String],function (s)
		{
			alert("new String('"+s+"')");
		}),
		new Method([Number],function (n)
		{
			alert("new Number("+n+")");
		});
	);
});

var d=new Data();
d.print("szöveg"); //a kimenet: "new String('szöveg')"
d.print(123); //a kimenet: "new Number(123)"
Ezt mondjuk szívesen használnám php-ben is... Én mondjuk szeretem a típusos nyelveket, mert lusta vagyok mindenhol is_string-et meg is_numeric-et írni, szerintem egy ilyen overload sokkal szebb, mint függvényt írni arra, hogy szétossza a kérést a példában a _print_string és _print_number között. Javascripttel gyakorlatilag mindent le lehet utánozni, ami a típusos nyelvekben van, mert annyira rugalmas. Kérdés, hogy megéri e? :-)

Ahogy nézem javascript 2.0-ban vannak már osztályok, meg típusos nyelv lett, de többet sajnos nem találtam róla. Lehet, hogy csak álom maradt? Ti tudtok valamit róla?
7

Nem hiszem, hogy csak ott...

inf3rno · 2010. Május. 1. (Szo), 01.56
Persze, van/lehet haszna, de szerintem leginkább a fejlesztői fázisban, nem az éles környezetben.

Nekem javascripttel az a tapasztalatom, hogy az ilyen closure-ozás nem szokott jelentősen lassítani, inkább a DOM függvények, meg az animációk, amik nagyon erőforrás igényesek...

Esetleg még olyan helyzetet el tudok képzelni, amikor mondjuk bejön kívülről (pl ajax) valamilyen típusú dolog, aztán try-catch-el döntöd el, hogy egy adott függvény lefusson rá, vagy sem.

Meg hát ha interface-eket akarsz betenni, akkor mondjuk egy ilyesmit el tudok képzelni beépített típusellenőrzéssel:

var iTest=new Interface(
{
	test: new Method(String,Number,Function)
});

var Sthg=new Class(
{
	test: function (a,b,c)
	{
		//valami implementáció
	}
}).implement(iTest);
Amint oda érek egy projektnél, összedobok egy ilyen osztályokkal dolgozó kis könyvtárat, párszáz sorból kijön az egész...
13

Érdemes még körbenézni a

T.G · 2010. Május. 5. (Sze), 09.31
Érdemes még körbenézni a "function overloading in JavaScript" illetve "method overloading in JavaScript" kifejezésekkel a Google-n, mert sok hasonlóval találkozhat az ember...

Szerintem azzal, hogy csak typeof irányba vizsgáljuk a paramétereket sokkal kisebbet lépünk, mint amekkora lehetőség volna itt. Ahhoz, hogy valóban legyen ennek értelme szerintem inkább instaceof -val kellene vizsgálni, hogy miféle Objektumot kaptunk. Ekkor talán valóság közelibb (?) példákat kaphatunk.

Engem tényleg érdekelne, hogy valójában létezik-e olyan élesben használt példa, amikor erre szükség van. Hiába nézem az itteni példákat, a neten található példákat, egyiket sem tudom elképzelni, hogy ilyen esetben ezt használnám. :)
Ezt leszámítva persze érdekes elképzelés.
14

Szerintem azzal, hogy csak

inf3rno · 2010. Május. 12. (Sze), 06.06
Szerintem azzal, hogy csak typeof irányba vizsgáljuk a paramétereket sokkal kisebbet lépünk, mint amekkora lehetőség volna itt. Ahhoz, hogy valóban legyen ennek értelme szerintem inkább instaceof -val kellene vizsgálni, hogy miféle Objektumot kaptunk. Ekkor talán valóság közelibb (?) példákat kaphatunk.


Ha jobban megnézed: van benne instanceof, csak valamiért a string,number,boolean típusoknál nem ment azzal.

Érdemes még körbenézni a "function overloading in JavaScript" illetve "method overloading in JavaScript" kifejezésekkel a Google-n, mert sok hasonlóval találkozhat az ember...


Körbenéztem, sok újat nem láttam. Próbáltam összehozni egy komolyabb rendszert osztályokkal meg interfacekkel, meg ilyesmivel, menni menne, csak most nincs rá egy hetem. :-) Nem is olyan egyszerű, mint amilyennek elsőre gondolja az ember, főleg ha már genericitás meg templatek is szóba kerülnek. Lehetne ilyen alapon egész keretrendszert írni, és szerintem nem is lenne rossz a fejlesztése, csak hát be vagyok táblázva augusztus végéig.
Még meglátom, lehet, hogy megírom valamikor a nyáron, aztán írok cikket róla, vagy csak kiteszem valahova. Egyelőre ha van szabadidőm, akkor inkább XML,XSLT,XSD,WSDL meg ilyesmik foglalkoztatnak, sokkal hasznosabbak, mint a javascriptes gányolás.
15

Végleges felület

inf3rno · 2010. Jún. 6. (V), 06.07
Közben kitaláltam egy egész elfogadható felületet osztályok, meg a típusosság egy részének megvalósítására. A decorator rész csak a háttérben működik benne, az overloadot meg inkább kihagytam belőle, bár azt is bele lehetne tákolni viszonylag kevés munkával.

Package.import(
{
	P: new Package(
	{
		initialize: function ()
		{
			alert(this.getName()+" csomag importálva.");
		},
		A: new Class(),
		I: new Interface(),
		B: new Class(
		{
			Implements: function ()
			{
				return this.Package.I;
			},
			Extends: function ()
			{
				return this.Package.A;
			},
			Types: function ()
			{
				return 
				{
					key: String,
					value: this.Class //vagy this.Package.B
				};
			},
			initialize: function ()
			{
				alert(this.Package.getName()+this.Class.getName()+" osztály példányosítva.");
			},
			test: function (key,value)
			{
				alert("Metódus: "+this.getName()+", kulcs: "+key+", érték: "+value.toString());
			},
			toString: function ()
			{
				return "{ class: "+this.Class.getName()+"}";
			}
		})
	})
}); 				// P csomag importálva.
var b=new P.B(); 	// P.B osztály példányosítva
var b2=new P.B();	// P.B osztály példányosítva
b.test("text",b2);	// Metódus: test, Kulcs: text, érték: { class: P.B}
Fontosnak tartottam, hogy az osztályok és a csomagok neveit ismerje a rendszer, és ezek az infok leérhetőek legyenek. A másik, ami számított, hogy nem akartam a névtereknél mindent egy closureba belesuvvasztani, aztán ott létrehozni. Inkább kompromisszumot kötöttem, és az Implements,Extends,Types részeket beleraktam az osztály megadásába. Ezzel mondjuk megoldódott az is, hogy az Extends meg Implements eddig az osztály blokkja után került, így viszont már az elejére is lehet tenni őket.
A megoldás nem a legszebb, lehetett volna még osztály szintű konstruktorral megcsinálni, de úgy gondoltam zavaró lenne a több konstruktor egy osztályon belül, főleg, hogy osztályfüggvények egyáltalán nincsenek, helyettük inkább a Singletont fogom bevezetni és használni mindenhol. (Esetleg a nagyon B) terv a nagybetűs osztályfüggvények bevezetése.)
A típuskezelést összevontam osztály szintre a metódusoknál a paraméterek neve alapján nézi, hogy milyen típust kell kapnia. Így osztály szinten egy paraméter csak egyvalamit jelölhet. Ez növeli az átláthatóságot, másrészt meg minden típust csak egyszer kell megadni osztály szinten. A típusok továbbörökítése így nagyon szimpla.
Absztrakt metódusról egyelőre gondolkozom, ami már biztos az interfacekkel kapcsolatban, hogy implementáció is lesz bennük, nem csak absztrakt rész. Gondolkodtam rajta, hogy külön veszem a megvalósítást "Fragment"-ekbe, de aztán letettem róla. Nem sokszor, de azért előfordult, hogy több osztályból kellettek volna függvények, ezzel a módszerrel meg nagyjából megoldható a dolog. Persze lehetne többszörös öröklés is helyette, de akkor meg a típuskezelés lenne még annál is bonyolultabb...

A new Class mellett még a new Singleton is szerepelni fog valószínűleg... Egyelőre még nem tudom, hogy egyből példányosítom e, amint felépült az osztály... Valszeg nem, max akkor, ha abszolut nem használok konstruktoros dependency injection-t...

Egyelőre így áll a szitu, a megoldása egész egyszerű lesz sztem, egyedül a függvény paraméter listájának kiolvasása okozhat némi gondot, de ha jól emlékszem regexel megoldottam már valamikor.

Néhány függvény dekorálásos dologra szükség lehet osztályon kívül is, pl defer (elhalasztja a fgv futását), vagy ilyesmik, a legtöbbre viszont nem igazán. Nagyjából ezzel felülettel szerintem megoldható az a káosz meg gányolás, ami a javascriptes osztályok írásánál van.

Legkésőbb július elején lesz implementáció hozzá, megpróbálom majd csatolni, vagy kitenni új blog bejegyzésbe, hátha érdekel valakit.
17

Üdv!

Karvaly84 · 2011. Szep. 20. (K), 23.34
Én most gondolkodok azon, hogy a osztályokat gyártó rutinomat ki kellene egészíteni, mert kezd az agyamra menni a sok if else, neten nézelődtem már, de érdekelne hogy végül az itt említett dologból lett e valami és ha igen akkor meg e tudom nézni valahol.
18

contracts.coffee

Poetro · 2011. Szep. 21. (Sze), 02.59
A CoffeeScript egy nyelvjárásában, a contracts.coffee-ban erre van lehetőséged, és ennek megfelelő JavaScript kódot fog neked generálni. Valamint általánosságban is kevesebbet kell gépelni CoffeeScript alatt.
19

köszönöm a segítséget, csak

Karvaly84 · 2011. Szep. 21. (Sze), 07.39
köszönöm a segítséget, csak az a probléma, hogy nem áll rá a kezem a coffee szintaxisra, már többször próbálkoztam vele :(
27

igen, de...

presidento · 2011. Okt. 13. (Cs), 12.53
Azt azért jó tudni, hogy az ilyen kód nem cross-browser (jelenleg csak FF4+ alatt fut, egyébként kihagyja az ellenőrzéseket).
20

Egyelőre még nem. Annyi a

inf3rno · 2011. Szep. 21. (Sze), 11.51
Egyelőre még nem. Annyi a probléma a dologgal, hogyha mondjuk megadsz egy csomagot, ahol a csomag elemei függenek egymástól, akkor problémák lesznek a feldolgozással...
pl:

$(
{
	'my': new Package(
	{
		'parentClass': new Class({...}),
		'descendantClass': new Class({...}).extends(my.parentClass)
	})
});
Ugye itt látszik, hogy a parentClass még létre sem jött, de már használni kéne.

Na most elég sokat agyaltam azon, hogy mi lenne az ideális módszer arra, hogy ezeket a függőségeket jelölni tudjam, de mégse szálljon el az egész rendszer, és ne is legyen túl bonyolult. A végén erre jutottam:

$(
{
	'package my':
	{
		'class parentClass': {...},
		'class descendantClass extends this.parentClass': {...}
	}
});
A feldolgozása azon alapul, hogy minden egyes sorból csinál egy tokent a rendszer, aminek le lehet kérni a függőségeit. pl a my.descendantClass létrehozásának a my.parentClass a függősége, a my.parentClass-nek meg a my csomag megléte a függősége. Ezek után sorba rakja a tokeneket függőség szerint, és utána végrehajtja őket egy megadott builder segítségével. Ez az egész viszonylag egyszerűen megvalósítható, csak egyrészt annyi dolgom volt az utóbbi fél évben, hogy egy percem sem jutott rá, másrészt érdeklődés sem nagyon volt az ügyben, úgyhogy bekerült a fiók mélyére... :-)
Most hétvégén össze tudok dobni egy nagyon alap rendszert, csomagokkal, osztályokkal, öröklődéssel, meg típusossággal. Szerintem néhány óra alatt megvan, mert az elemeit elég sokat használtam, már csak össze kell illeszteni őket...
21

Én nem ennyire bonyolult

Karvaly84 · 2011. Szep. 21. (Sze), 13.12
Én nem ennyire bonyolult dologra számítottam :D

Nekem csak annyi kéne, hogy a funkcióknak legyen változó szignatúrája típusokkal. Pl én a osztály gyártást beírtam a Function.prototype-be.

var Class = Object.extend({
   constructor : function() {
      /*
       * Ide szeretnék tenni valamit amivel
       * elérem a poliformizmust.
       * Valami olyasmire gondoltam, hogy ezt a dolgot
       * is a Function.prototype-be teszem. Mondjuk
       * egy "overload" nevű metódussal amiben a
       * típusok vannak majd a legutolsó paraméter
       * egy callback függvény, és az alábbi módon használnám:
       */
       try {
           arguments.callee.signature.apply(this, arguments);
       } catch (e) {
           throw new Error('Rossz paraméter lista!');
       }
   }; 
});

Class.overload(String, String, function(name, value) {
    this.name = value;
});

Class.overload(Object, function(opt) {
    for (var k in opt) {
        this[k] = opt[k];
    }
});
Az overloading-ot még nem programoztam le, csak elsőre nekem ilyen felület ugrott be, még nézelődök a témában, de azért véleményt ha adnál erre megköszönném, hogy ez a megoldás életképes e.
22

Jó, hát ez a konstruktorokra

inf3rno · 2011. Szep. 21. (Sze), 14.40
Jó, hát ez a konstruktorokra működik, de mi van a metódusokkal? Meg hogyan oldanád meg az öröklést? Meg hogyan tudsz megadni a legátláthatóbban egy teljes osztályt?
23

Az öröklődést már megoldottam

Karvaly84 · 2011. Szep. 21. (Sze), 15.41
Az öröklődést már megoldottam pár egyszerü sorral:


// Kiterjesztés a Function osztályhoz.

(function() { // this = Function.prototype

	
	// Öröklődés.
	
	var PrototypeChain = new Function();
	
	this.extend = function(proto) {
		if (!proto) proto = new Object();
		var Class, k;
		Class = proto.hasOwnProperty('constructor') ? proto.constructor : proto.constructor = new Function();
		PrototypeChain.prototype = this.prototype;
		Class.prototype = new PrototypeChain();
                Class.prototype.__super__ = this;
		for (k in proto) {
			Class.prototype[k] = proto[k];
		}
		return Class
	};
}).call(Function.prototype);
Na most úgy gondolom ha a Function.prototype-be teszek egy overload metódust akkor ha egy függvényre rá teszek egy szignaturát egy callback függvénnyel akkor az öröklődik a metódussal együtt, az overload függvény a hozzá tartozó függvényen le rak egy tömböt amiben kotorászik, igy a tömb is öröklődik, gondolom. És pont amit mondasz hogy hogyan lesz ez átlátható ezen filózok. Mert ha pl egy closure-ben hozom létre a osztályt ahol fontos hogy a callback-ok is ki lássanak az éterbe akkor elég csúnya a kivitel. Pl tegyük fel hogy van egy burkoló osztályunk:

var checkNodeType = function() {
	// return true or false
};

var Node = Object.extend({
	constructor : (function() {
		var constructor = function() {
			constructor.form.call(this, arguments);
		}
		constructor.overload(Object, function(node) {
			if (checkNodeType(node)) {
				this.node = node;
			} else {
				throw new Error();
			}
		});
		return constructor;
	})(),
	setAttribute : (function() {
		var settAttribute = function() {
			settAttribute.form.call(this, arguments);
		};
		settAttribute.overload(Object, function(attr) {
			for (var k in attr) {
				this.node.setAttribute(k, attr[k]);
			}
		});
		return setAttribute;
	})()
});

var Element = Node.extend({
	constructor : (function() {
		var constructor = function() {
			constructor.form.call(this, arguments);
		};
		constructor.overload(Object, function(node) {
			this.__super__.call(this, node);
		});
		constructor.overload(String, function(tagName) {
			var elem = document.createElement(tagname);
			this.__super__.call(this, elem);
		});
		constructor.overload(String, Object, function(tagName, attr) {
			var elem = document.createElement(tagName);
			this.__super__.call(this, elem);
			this.setAttribute(attr);
		});
		return constructor;
	})()
});
Most ezt csak össze csaptam elméletben így működne. De marha sok a zárójel...
az overload azt csinálná hogy a függvénynek adna egy form nevü tulajdonságot ha az még nem lenn, és ez a tulajdonság a Form nevű osztály egy példánya lenne ami globálisan nem elérhető, ezen az osztályon dolgozna a overload metódus, ennek az osztálynak lennének olyan metódusai hogy indexOf, call, addSignature, stb, és így azt hiszem meg lehetne oldani hogy a szignatúrák is vándoroljanak öröklödésnél.
24

Na hát ez a különbség ahhoz

inf3rno · 2011. Szep. 21. (Sze), 16.36
Na hát ez a különbség ahhoz képest, amit én írtam :D

A lényeg, hogy tömören és átláthatóan gyűjteményekkel lehet megadni dolgokat. Mondjuk egy js object vagy egy tömb egy gyűjtemény. A gyűjtemények elemeinél le lehet tárolni feldolgozással kapcsolatos utasításokat. Én ezeket a példámban a kulcsban tárolom, de természetesen az érték oldalon is megadhatóak. Ezután fogod a gyűjteményedet és végig mész minden elemén, és mindegyiket feldolgozod az utasítás szerint. A lényeg, hogy így nem kell a kódban könyékig turkálnod, mert azt elintézi neked a feldolgozó programod...
25

Ami neked idáig megvan

Karvaly84 · 2011. Szep. 21. (Sze), 16.42
Ami neked idáig megvan forráskód azt tanulmányozhatnám valahol? Mert elképzelhető, hogy ki ragadnék belőle pár ötletet, ha nem gond.
26

Az kicsit össze-vissza ahogy

inf3rno · 2011. Szep. 21. (Sze), 18.54
Az kicsit össze-vissza ahogy nézem, nem hiszem, hogy sokat értenél belőle :S
Gyere skype-ra laszlo.janszky.
16

2006-ból

Joó Ádám · 2010. Jún. 6. (V), 15.30
John Resig 2006-os Pro JavaScript Techniques c. kötetében találtam egy megvalósítást.