Autor | Zpráva | ||
---|---|---|---|
Darker Profil |
#1 · Zasláno: 17. 7. 2011, 23:44:05
Nedávno jsem náhodou, v souvislosti s mícháním položek pole, oběvil možnost jak poli (array) přiřadit členskou funkci. Vlastně ne poli, ale polím, všem.
Array.prototype.vlastnost=/* ... */; To se mi náramně líbí, ale nějak se mi nedaří najít ostatní datové typy. Chtěl bych podobné věci provádět i se string a int... |
||
Leo Profil |
#2 · Zasláno: 17. 7. 2011, 23:54:08
String (záleží na velikosti písmen); int není v JS žádný datový typ, tím je number (konstruktor zase s velkým písmenem: Number.prototype....). Leo
|
||
DJ Miky Profil |
#3 · Zasláno: 18. 7. 2011, 09:41:30
Ještě ostatní datové typy:
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects#Constructors |
||
Witiko Profil |
#4 · Zasláno: 18. 7. 2011, 16:25:18
Jenom doporučuji na začátku funkcí s
Number a String získat prostou hodnotu pomocí var value = this.valueOf(); Tím se setřou rozdíly mezi voláním z prostého datového typu (2 , "ahoj" ) a immutable objektu (new Number(2) , new String("ahoj") ).
|
||
Witiko Profil |
#5 · Zasláno: 18. 7. 2011, 16:27:21 · Upravil/a: Witiko
Přihodím pár svých kreativních ukázek, co se s tím dá na vestavěných objektech dělat:
Number.prototype.times = function(f) { // Metoda inspirovaná Ruby var index = this; if(/\./.test(index) || index <= 0) return; while(index-- > 0) f(); }; (3).times(function() { alert("Ahoj světe!"); // Třikrát vypíše "Ahoj světe!" }); Boolean.prototype.bitify = function() { return this.valueOf()?1:0; }; alert((1 + 2 === 3).bitify()); // Vypíše 1 Array.prototype.random = function() { var l; return this[ (l = this.length) <= 1? 0:Math.ceil( Math.random() * l ) - 1 ]; }; [1, 2, 3, 4, 5, 6].random(); // Hrací šestihranná kostka String.prototype.numberOf = function(needle) { var num = 0, lastIndex = 0; if(needle instanceof RegExp) { if(!needle.global) { var flags = "g"; if(needle.ignoreCase) flags += "i"; if(needle.multiline) flags += "m"; needle = new RegExp(needle.source, flags); } return (num = this.match(needle)) !== null?num.length:0; } else { if(typeof needle !== "string" && !(needle instanceof String)) needle = needle.toString(); while((lastIndex = this.indexOf(needle, lastIndex) + 1) > 0) num++; return num; } }; alert("Řekl jste " + "A Ehm, jasně tu ehm vidíme, že ehm...".numberOf(/ehm/i) + "x ehm!"); // Vypíše Řekl jste 3x ehm! Function.prototype.extends = function(object) { // Ne simulace třídní dědičnosti, ale drobná pomoc s tou prototypální var f = new Function; f.prototype = object.prototype; this.prototype = new f; this.prototype.constructor = this; }; function a() {}; a.prototype.a = 1; function b() {}; b.extends(a); b.prototype.b = 2; var c = new b(); alert(c.a + c.b); // Vypíše 3 |
||
_es Profil |
#6 · Zasláno: 18. 7. 2011, 16:45:55 · Upravil/a: _es
Witiko:
„Tím se setřou rozdíly mezi voláním z prostého datového typu (2, "ahoj") a immutable objektu (new Number(2), new String("ahoj")).“ Jednoduché dátové typy sú aj tak predtým konvertované na im prislúchajúce objektové rozšírenia. Metóda f nemá možnosť zistiť rozdiel medzi zavolaním (8).f() a (new Number(8)).f() .
Doplnenie: v strict móde sa to zistiť dá, objektový obal nie je vytváraný, napríklad vyskúšaním v novom Firefoxe alebo Chrome: javascript:"use strict";Number.prototype.f=function(){alert(typeof this)};(10).f()
|
||
Witiko Profil |
#7 · Zasláno: 18. 7. 2011, 16:53:56 · Upravil/a: Witiko
_es:
Zvláštní, teď jsem to testoval a je tomu skutečně tak. Zvláštní je to, protože vím, že v minulosti jsem se setkal s tím, že metoda byla spouštěna v kontextu původní hodnoty - tzn. že v this při spuštění nad prostou hodnotou nebyl objekt, ale prostá hodnota. Ale buďto to byla ojedinělá záležitost nebo jsem se tenkrát zmýlil, protože se skutečně zdá, že tomu tak není, viz.:
String.prototype.test = function() { alert(this instanceof String); }; new String("abc").test(); // true "abc".test(); // true Edit: To to vyjasňuje. Se strict mode m jsem si hrál. Děkuju za objasnění. :-)
|
||
Darker Profil |
#8 · Zasláno: 18. 7. 2011, 21:25:37
Děkuji moc za informace, ušetří mi to v budoucnu spousta práce. (přinejmenším ušetřím hafo globálních proměnných)
|
||
Darker Profil |
#9 · Zasláno: 18. 7. 2011, 22:51:25
Ještě jsem se chtěl zeptat, existuje možnost definovat proměnné funkci, která se bude chovat jak vlastnost? Mám na mysli třeba length. Tak něco podobného.
|
||
Witiko Profil |
#10 · Zasláno: 19. 7. 2011, 02:04:00 · Upravil/a: Witiko
Darker:
Říká se tomu accessory. Funguje to tak, že si nadefinuješ vlastnost objektu a nastavíš jí tzv. getter a setter metody (nebo jen jednu z nich). Ta první je volaná když zjišťuješ hodnotu vlastnosti, ta druhá pak při změně / přiřazení nové hodnoty vlastnosti. Před tím než přišla oficiální podpora se poměrně rozmohly nestandardní metody of Mozilly: Object.prototype.__defineGetter__(vlastnost, funkce); // Definuje getter Object.prototype.__defineSetter__(vlastnost, funkce); // Definuje setter Object.prototype.__lookupGetter__(vlastnost); // Navrátí getter Object.prototype.__lookupSetter__(vlastnost); // Navrátí setter ECMA5 pak (relativně) nově umožňuje definici přes změněnou syntax: var objekt = { get a() {}, set a() {} } try a catch na ECMA 3.1 zařízeních, která hážou SyntaxError jak jen tento pseudo-JSON objekt z dálky koutkem oka zahlédnou. Pak je také možné deklarovat accessory pomocí metody Object.defineProperty . S tou je zase jiná švanda, jelikož Internet Explorer 8 ji implementuje, ale jen pro DOM Elementy (9 už by měla být v pořádku) - Takže opět odchytávání pomocí try a catch .
Neměl by být problém napsat menší knihovnu, která tyto dvě implementace zastřeší - vlastně už jsem něco takového před časem na zkoušku sepsal, nicméně reálné nasazení je bohužel kvůli nepodpoře na Internet Exploreru < 9 nemožné. Navíc reálné využití pro accessory je spíše sporadické (Chamurappiho implementace vlastnosti innerText pro Mozillu), jelikož co dokáže accessor, to umí i funkce. Accessory nabízí jen abstraktnější přístup a čistší zápis, což jsou pěkné věci, nicméně zatím se to myslím všeobecně nevyplatí.
({ get a() {console.log("Ahoj ")}, set a() {console.log("světe!");} }).a++; // Vypíše Ahoj světe! |
||
Časová prodleva: 13 let
|
0