Autor Zpráva
Darker
Profil
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
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
Ještě ostatní datové typy:
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects#Constructors
Witiko
Profil
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
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
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
_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 modem jsem si hrál. Děkuju za objasnění. :-)
Darker
Profil
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
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
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
Jednoduchá a zároveň zcela dostačující implementace.

ECMA5 pak (relativně) nově umožňuje definici přes změněnou syntax:
var objekt = {
  get a() {},
  set a() {}
}
Což je pak možné chytat přes 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!

Vaše odpověď

Mohlo by se hodit

Neumíte-li správně určit příčinu chyby, vkládejte odkazy na živé ukázky.
Užíváte-li nějakou cizí knihovnu, ukažte odpovídajícím, kde jste ji vzali.

Užitečné odkazy:

Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0