Překlad článku Introducing ECMAScript 5.1 (autor: Mike Taylor) z webu Dev.Opera. Překlad vychází s laskavým svolením Opera Software.
Úplný seznam novinek naleznete v přílohách D a E v oficiální specifikaci ECMAScriptu (PDF) na webu http://www.ecmascript.org/; v HTML podobě jej najdete na stránkách Michael[tm] Smith’s unofficial annotated HTML version.
Podpora ES5.1 v prohlížečích
S vydáním Opery 11.60 je ES5 podporován ve všech pěti hlavních prohlížečích. Pokud nebude řečeno jinak, budou všechny dále zmiňované vlastnosti dostupné v těchto verzích (a vyšších):
- Opera 11.60
- Internet Explorer 9*
- Firefox 4
- Safari 5.1**
- Chrome 13
* IE9 zatím nepodporuje strict mode, až ve verzi IE10.
** V Safari 5.1 stále není podpora pro Function.prototype.bind
, ačkoli před nedávnem byla přidána do Webkitu
.
Stav podpory ve starších prohlížečích naleznete na stránce ECMAScript 5 compatibility table od Jurije Zajceva (Juriy Zaytsev).
Strict Mode v ES5
Strict mode (viz ECMAScript Strict mode ve Firefoxu 4) je způsob, jakým se vývojář může přihlásit k restriktivnější verzi jazyka, která přináší vyšší bezpečnost a spolehlivost. Strict mode je nastaven přidáním direktivy "use
na začátek souboru nebo funkce. Protože je tato direktiva prostý řetězec, bude bez problémů staršími prohlížeči ignorována.
strict";
"use strict";
function strict(){ "use strict"; //... } function sloppy(){ eval("window.foo = 'bar'"); }
Mnoho věcí, které v normálním JavaScriptu způsobí nepředvídatelné chybné chování, způsobí ve strict mode výjimku, kupříkladu:
- Přiřazení do nedeklarované proměnné vyhodí
ReferenceError
(v prostém JS vytvoří globální proměnnou). - Vícenásobné přiřazení do stejně pojmenované vlastnosti v objektovém zápisu vyvolá
SyntaxError
. - Byla odstraněna konstrukce
with
. Její použití vyvoláSyntaxError
.
Pěkné shrnutí těchto rozdílů naleznete v článku na MDSN.
JSON
ES5 zavádí globální objekt JSON
, který slouží k serializaci ( JSON.stringify
) a deserializaci ( JSON.parse
) objektů do/z formátu JSON.
U starších prohlížečů lze použít polyfill skript json2.js od Douglase Crockforda, který poskytuje stejnou funkčnost (samosebou nejprve otestuje nativní podporu).
JSON.parse(text [, reviver])
JSON.parse
bere řetězec (ve formátu JSON) a vrací hodnotu. Volitelný parametr reviver je funkce s dvěma argumenty, key
a value
, která je provedena nad výsledky, což je umožňuje filtrovat a měnit před tím, než jsou vráceny.
>> var result = JSON.parse('{"a": 1, "b": "2"}'); Object >> result.b "2"
Pokud se chceme ujistit, že výsledkem bude celé číslo (nikoli řetězec), použijeme tuto funkci.
var result = JSON.parse('{"a": 1, "b": "2"}', function(key, value){ if (typeof value == 'string'){ return parseInt(value); } else { return value; } }) >> result.b 2
JSON.stringify(value [, replacer [, space]])
JSON.stringify
bere hodnotu a převádí ji na řetězec ve formátu JSON. V nejjednodušší podobě přebírá jednu hodnotu a vrací řetězec.
>>> var mike = JSON.stringify({mike: "taylor"}) undefined >> mike '{"mike": "taylor"}' >> typeof mike "string"
Když potřebujeme změnit způsob, jakým je hodnota převedena na řetězec, nebo filtrovat data, můžeme předat funkci replacer
. Kupříkladu pokud chceme vynechat hodnotu 13, můžeme to provést takto:
var nums = { "first": 7, "second": 14, "third": 13 } var luckyNums = JSON.stringify(nums, function(key, value){ if (value == 13) { return undefined; } else { return value; } }); >> luckyNums '{"first": 7, "second": 14}'
Pokud funkce replacer vrátí hodnotu undefined
, nebude tento klíč ve výsledném JSON zahrnut. Třetím argumentem je počet mezer, kterým se má odsadit zanoření (kvůli lepší čitelnosti výsledného textu), nebo řetězec, který je přidán jako výplň odsazování. Hodnoty větší než 10 jsou převedeny na 10, řetězec delší než 10 znaků je oříznut a je použito pouze prvních deset znaků.
var luckyNums = JSON.stringify(nums, function(key, value) { if (value == 13) { return undefined; } else { return value; } }, 2); >> luckyNums '{ "first":7, "second":14 }'
Rozšíření Object
Ke konstruktoru Object
byly přidány následující metody:
Object.getPrototypeOf
Object.getOwnPropertyDescriptor
Object.getOwnPropertyNames
Object.create
Object.defineProperty
Object.defineProperties
Object.seal
Object.freeze
Object.preventExtensions
Object.isSealed
Object.isFrozen
Object.isExtensible
Object.keys
Jednou z výhod je lepší řízení práce s vlastnostmi objektu, např. určení, které lze měnit, procházet, mazat apod. Tyto možnosti se nastavují pomocí tzv. property deskriptorů. Kupříkladu:
var cat = {}; Object.defineProperty(cat, "name", { value: "Maru", writable: false, enumerable: true, configurable: false }); Object.defineProperty(cat, "skill", { value: "exploring boxes", writable: true, enumerable: true, configurable: true });
U našeho objektu cat
nelze měnit vlastnost name
, ale objeví se při procházení smyčkou for-in
(enumerable). Kromě jiného je Maru dobrá v prozkoumávání krabiček, ale tato schopnost může být v budoucnu změněná, tak má vlastnost skill
ponechané příznaky writable
a configurable
.
V některém z dalších článků se k těmto vlastnostem vrátíme.
Vylepšení polí
K prototypu Array
byly přidány následující možnosti:
Array.prototype.indexOf
Array.prototype.lastIndexOf
Array.prototype.every
Array.prototype.some
Array.prototype.forEach
Array.prototype.map
Array.prototype.filter
Array.prototype.reduce
Array.prototype.reduceRight
Dmitrij Šošnikov (Dmitry Soshnikov) napsal podrobný článek o těchto rozšířeních polí v ES5.
Jedna metoda, kterou Dmitrij v článku nezmínil, je Array.isArray
, která je přidána přímo ke konstruktoru, nikoli k prototypu. Array.isArray
dělá to, co od něj očekáváme – je to metoda, která vrátí true
nebo false
podle toho, jestli vnitřní vlastnost [[Class]]
je rovna „Array“.
Array.isArray("NO U") >> false Array.isArray(["NO", "U"]) >> true
V ES3 byl jediný použitelný způsob, jak určit, zda je hodnota pole nebo ne, takzvaný „the Miller Device“, neboli porovnání interní vlastnosti [[Class]]
s tou, kterou má pole.
Object.prototype.toString.apply(value) === '[object Array]'
Function.prototype.bind(thisArg [, arg1 [, arg2, …]])
Function.prototype.bind
vrací novou funkci, u níž je hodnota this nastavena podle argumentu thisArg
. To umožňuje vykonat funkci v kontextu jiného objektu
function locate(){ console.log(this.location); } function Maru(location){ this.location = location; } var kitty = new Maru("cardboard box"); var locateMaru = locate.bind(kitty); locateMaru();
V tomto příkladu voláme funkci location
v kontextu objektu Maru. Protože locate
je vlastností globálního objektu, je v něm this
rovno právě globálnímu objektu ( window
). V našem případě hledáme kočku, nikoli objekt Location
, takže si vytvoříme novou funkci locateMaru
, kde je hodnota this
svázána s kitty
.
Další zdroje informací
- ECMAScript 5 Objects and Properties John Resig
- Understanding JavaScript Function Invocation and “this” Yehuda Katz
- JavaScript Strict Mode Angus Croll
- ECMA-262–5 in detail: Introduction Dmitry Soshnikov
- ECMAScript 5 compatibility table Juriy Zaytsev
Přehled komentářů