Scott Tiger Tech Blog

Blog technologiczny firmy Scott Tiger S.A.

ECMAScript 5

Autor: Piotr Karpiuk o czwartek 15. Marzec 2012

Zaakceptowana oficjalnie w 1999 wersja 3 ECMAScript jest pewną bazą wszystkich implementacji języka JavaScript w dzisiejszych przeglądarkach. Tym niemniej, język się rozwija i dziś w najnowszych przeglądarkach jest już zaimplementowana obsługa ECMAScript 5, co dokładniej pokazuje tabelka (na skutek różnych perturbacji wersja 4 została zarzucona). Ba, mówi się już o wersji 6 (nazwa kodowa Harmony), której specyfikacja ma być gotowa na koniec 2013 roku, a niektóre przeglądarki (np. Google Chrome 19) już eksperymentalnie zaimplementowały niektóre zawarte tam nowinki – ale o tym innym razem. Przedmiotem dzisiejszego posta jest ECMAScript 5.

Przydatne odnośniki
ECMAScript 5.1 Spec

Wersja 5 nie zawiera żadnych rewolucyjnych zmian, zwłaszcza składniowych. Jest zestawem modyfikacji poprawiających bezpieczeństwo, jak również długo oczekiwanych usprawnień. O ile nie włączymy trybu ścisłego (o czym za chwilę), jest również zgodna wstecz.

Strict mode

Tryb ścisły (ang. strict mode) usuwa z języka pewne funkcje i wymusza określony styl kodowania, co czyni program prostszym i bardziej odpornym na błędy. Naruszenie dyscypliny powoduje wyjątek. Tryb ścisły włączamy umieszczając na początku zakresu zmiennych (na poziomie funkcji lub globalnym) łańcuch "strict mode" – starsze implementacje języka po prostu go zignorują. Planuje się, że w przyszłości tryb ścisły będzie jedynym dostępnym trybem.

W trybie ścisłym wyjątek spowoduje np.:

  • użycie zmiennej bez jej wcześniejszej deklaracji,
  • modyfikacja atrybutów obiektu niezgodnie z określoną polityką – patrz punkt „Object & Property System” w dalszej części,
  • usuwanie zmiennej,
  • definiowanie w jednym obiekcie dwóch własności o tej samej nazwie, lub w sygnaturze funkcji dwóch parametrów o tej samej nazwie:
              var x = { foo: true, foo: false }; // błąd
              function f(foo, foo) { ... }; // błąd
  • korzystanie wewnątrz funkcji z arguments.caller i arguments.callee,
  • użycie konstrukcji with.

JSON

W ECMAScript 5 pojawiła się wreszcie natywna implementacja funkcji konwertującej struktury danych na JSON (JSON.stringify(value[, replacer[, space]])) i odwrotnie (JSON.parse(text[, reviver])).

      var obj = JSON.parse('{"name":"Jan"}');
      var str = JSON.stringify({ name: "Jan", last: "Kowalski" }, null, 2);

W przypadku obu funkcji można podać drugi parametr który pozwala w locie modyfikować proces konwersji – szczegóły w dokumentacji, natomiast w funkcji stringify() można też podać trzeci parametr, który określa wcięcia używane przy formatowaniu JSONa (brak tego parametru oznacza brak formatowania).

Nowe metody w klasach Function, Array, Date

Object & Property System

Przywykliśmy traktować obiekt JavaScriptu jak słownik, w którym kluczami są łańcuchy a wartościami cokolwiek. Jest to dość prymitywne podejście do obiektowości, które utrudnia wdrożenie dyscypliny koniecznej do tworzenia większych programów. O ile wcześniej własność obiektu miała jedynie nazwę i wartość, to teraz każda własność ma nazwę i deskryptor (ang. property descriptor) z następującymi atrybutami:

  • value, writable – wartość własności i flaga określająca czy można zmieniać tą wartość,
  • enumerable – flaga, która mówi czy własność pojawi się podczas iterowania obiektu za pomocą for(var key in obj) { ... },
  • get, set – funkcje kontrolujące dostęp do wartości własności (wołane przy próbie odpowiednio odczytu lub zapisu wartości); Uwaga: własność może mieć zdefiniowane albo atrybuty value/writable (jest to tzw. data descriptor), albo get/set (accessor descriptor),
  • configurable – flaga, której wartość false oznacza, że własności nie można usunąć, a deskryptor własności nie może być modyfikowany (z wyjątkiem atrybutu writable, który może być przestawiony na false).

Domyślne wartości atrybutów deskryptora to false (dla flag) i undefined w pozostałych przypadkach.

Metoda Object.defineProperty(obj, prop, descriptor) tworzy nową własność lub modyfikuje istniejącą:

      var o = {};
      Object.defineProperty(o, "a", {value : 37,
                                     writable : true,
                                     enumerable : true,
                                     configurable : true});
      var bValue;
      Object.defineProperty(o, "b", {get : function(){ return bValue; },
                                     set : function(newValue){ bValue = newValue; },
                                     enumerable : true,
                                     configurable : true});
      o.b = 38;
    

Object.defineProperties(obj, props) jest skrótem zastępującym wielokrotne wywołania poprzedniej metody. Deskryptor wskazanej własności obiektu (nie dziedziczonej z prototypu) można otrzymać wywołując metodę Object.getOwnPropertyDescriptor(obj, propName). Object.keys(obj) zwraca tablicę wyliczalnych własności nie odziedziczonych z prototypu, a Object.getOwnPropertyNames(obj) listę wszystkich własności nie odziedziczonych z prototypu.

Object.create(proto[, propertiesObject]) tworzy nowy obiekt z podanym prototypem i własnościami określonymi tak jak w przypadku defineProperties().

Metoda Object.preventExtensions(obj) nieodwracalnie blokuje możliwość dodawania własności do wskazanego obiektu (nie mówi nic o usuwaniu), a Object.isExtensible(obj) zwraca stan flagi. Mocniejsze działanie ma metoda Object.seal(obj), która dodatkowo ustawia atrybut configurable wszystkich własności obiektu na false (co, przypomnijmy, zabrania usuwać własności), a Object.isSealed(obj) zwraca stan flagi.

Najmocniejsze działanie ma Object.freeze(obj), która dodatkowo blokuje nawet możliwość zmiany atrybutu writable deskryptorów własności obiektu, czyniąc obiekt autentycznie niemodyfikowalnym (ang. immutable). Jak się można domyśleć, Object.isFrozen(obj) zwraca stan flagi.

Inne zmiany

  • wsparcie dla Unicode 3.0,
  • w literale łańcuchowym dozwolony jest znak końca wiersza poprzedzony backslashem (czytaj: można tworzyć wielowierszowe literały łańcuchowe).
Share and Enjoy:
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Śledzik
  • Blip
  • Blogger.com
  • Gadu-Gadu Live
  • LinkedIn
  • MySpace
  • Wykop

Zostaw komentarz

XHTML: Możesz użyć następujących tagów: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>