Slide 1

Slide 1 text

Rubyist’s Quick Guide to ECMAScript 5 Kuba Suder @psionides • jsuder • http://psionides.eu • Lunar Logic

Slide 2

Slide 2 text

ECMA-what?...

Slide 3

Slide 3 text

ECMA-what?... • What you know as JavaScript, as an ECMA standard • “an unwanted trade name that sounds like a skin disease” – Brendan Eich

Slide 4

Slide 4 text

ECMA-what?... • What you know as JavaScript, as an ECMA standard • “an unwanted trade name that sounds like a skin disease” – Brendan Eich • ECMAScript 3 • Last version before ES5 – released in 1999 (!)

Slide 5

Slide 5 text

ECMA-what?... • What you know as JavaScript, as an ECMA standard • “an unwanted trade name that sounds like a skin disease” – Brendan Eich • ECMAScript 3 • Last version before ES5 – released in 1999 (!) • ECMAScript 4 • Dark ages: developed for 10 years, then abandoned

Slide 6

Slide 6 text

ECMA-what?... • What you know as JavaScript, as an ECMA standard • “an unwanted trade name that sounds like a skin disease” – Brendan Eich • ECMAScript 3 • Last version before ES5 – released in 1999 (!) • ECMAScript 4 • Dark ages: developed for 10 years, then abandoned • ECMAScript 5 • Minor update to ES3 to unify the various dialects and engines (2009)

Slide 7

Slide 7 text

ECMA-what?... • What you know as JavaScript, as an ECMA standard • “an unwanted trade name that sounds like a skin disease” – Brendan Eich • ECMAScript 3 • Last version before ES5 – released in 1999 (!) • ECMAScript 4 • Dark ages: developed for 10 years, then abandoned • ECMAScript 5 • Minor update to ES3 to unify the various dialects and engines (2009) • ECMAScript 6 / Harmony • The future – lets, arrows, classes and all the other cool stuff

Slide 8

Slide 8 text

ECMAScript 5 • Subset of ES4 – the least controversial parts • Extensions for: • Array • Date • Function • Object • String • Safe JSON parsing • Extended object properties • Strict mode

Slide 9

Slide 9 text

Array extensions • Array.isArray • map • filter • reduce, reduceRight • every • some • forEach • indexOf, lastIndexOf

Slide 10

Slide 10 text

Array.isArray Array.isArray([]); // => true Array.isArray(7); // => false • old way: x instanceof Array • old (proper) way, works across frames: Object.prototype.toString.call(x) === ‘[object Array]’

Slide 11

Slide 11 text

Array#map ['lunar', 'logic', 'polska'].map(function(el, i, arr) { return el[0].toUpperCase(); }); // => [‘L’, ‘L’, ‘P’] = Enumerable#map in Ruby

Slide 12

Slide 12 text

Array#filter ['Ruby', 'Java', 'Perl', 'PHP'].filter(function(el, i, arr) { return el.match(/r/i); }); // => [“Ruby”, “Perl”] • unfortunately there’s no “Enumerable#detect”... = Enumerable#select in Ruby

Slide 13

Slide 13 text

Array#reduce var a = [4, 8, 15, 16, 23, 42]; a.reduce(function(sum, el, i, arr) { return sum + el }); // => 108 a.reduce(function(sum, el) { return sum + el }, 9000); // => 9108 • there’s also Array#reduceRight and it does exactly what you think = Enumerable#inject in Ruby

Slide 14

Slide 14 text

Array#every var countries = ['Poland', 'Portugal', 'Peru']; var startsWithP = function(el, i, arr) { return el.match(/^P/); }; countries.every(startsWithP); // => true countries.push("India"); countries.every(startsWithP); // => false = Enumerable#all? in Ruby

Slide 15

Slide 15 text

Array#some var names = ['Marcin', 'Łukasz', 'Michał']; var endsWithA = function(el, i, arr) { return el.match(/a$/); }; names.some(endsWithA); // => false names.push("Ania"); names.some(endsWithA); // => true = Enumerable#any? in Ruby

Slide 16

Slide 16 text

Array#forEach ['one', 'two', 'three'].forEach(function(el, i, arr) { console.log(i + ": " + el); }); // 0: one // 1: two // 2: three • problem: no “break” instruction • use Array#every or Array#some and return false/true to stop • or use exceptions = Array#each in Ruby

Slide 17

Slide 17 text

Array#indexOf, #lastIndexOf var list = ['a', 'b', 'c', 'd', 'a', 'b', 'c']; list.indexOf('c'); // => 2 list.indexOf('c', 3); // => 6 list.lastIndexOf('c'); // => 6 • yes, this really didn’t exist before ES5 (including IE8!) = Array#index, #rindex in Ruby

Slide 18

Slide 18 text

Other extensions • Date.now • Date#toISOString • String#trim • String#trimLeft • String#trimRight • Function#bind

Slide 19

Slide 19 text

Date.now var d = Date.now(); // => 1365692504996 var date = new Date(d); date.toISOString(); // => "2013-04-11T15:01:44.996Z" = Time.now.to_i in Ruby

Slide 20

Slide 20 text

String#trim, #trimLeft, #trimRight var str = " text "; str.trim(); // => "text" str.trimLeft(); // => "text " str.trimRight(); // => " text" = String#strip, #lstrip, #rstrip in Ruby

Slide 21

Slide 21 text

Function#bind var a = { city: "Krakow", printCity: function() { console.log(this.city) } }; a.printCity(); // => "Krakow" var printCity = a.printCity; printCity(); // => undefined (this == window) var boundPrint = a.printCity.bind(a); boundPrint(); // => "Krakow" (this == a) = $.proxy, _.bind

Slide 22

Slide 22 text

JSON parsing var json = ‘{"a":1,"b":{"c":2}}’; var obj = JSON.parse(json); // => { a: 1, b: { c: 2 }} JSON.stringify(obj); // => "{\"a\":1,\"b\":{\"c\":2}}" • you could use eval, but eval is evil (just ask Crockford) • polyfill: json2.js (by Crockford) • included in IE8 (!)

Slide 23

Slide 23 text

Object extensions • Getters and setters • Protecting objects • Defining properties • Object introspection • Prototypal inheritance

Slide 24

Slide 24 text

Getters & setters var obj = { get v() { return 42 }, set v(x) { this.x = x } }; obj.v = 5; console.log(obj.v); // => 42

Slide 25

Slide 25 text

Protecting objects • Object.preventExtensions(o) • New fields can’t be added • Object.isExtensible(o) === false • Object.seal(o) • Fields can’t be added or deleted • Object.isSealed(o) === true • Object.freeze(o) • Fields can’t be added, deleted or modified • Object.isFrozen(o) === true

Slide 26

Slide 26 text

Defining object properties var obj = {}; Object.defineProperty(obj, 'x', { value: 5, writable: false }); obj.x; // => 5 obj.x = 1; obj.x; // => still 5 • other options: • get, set – specifies getter/setter • enumerable – tells if the field is listed when iterating with “for i in ...” • configurable – if the field can be deleted or its properties changed

Slide 27

Slide 27 text

Object introspection var obj = { x: 1 }; Object.keys(obj); Object.getOwnPropertyNames(obj); // => ["x"] (like Hash#keys) Object.getOwnPropertyDescriptor(obj, 'x'); // => { value: 1, writable: true, enumerable: true, // configurable: true } var a = []; Object.getPrototypeOf(a); // => Array.prototype

Slide 28

Slide 28 text

Prototypal inheritance var Fruit = { color: ‘red’ }; var apple = Object.create(Fruit); apple.__proto__; // => Fruit apple.color; // => ‘red’ • objects inheriting from objects, instead of classes inheriting from classes • was possible before, but required creating an anonymous class

Slide 29

Slide 29 text

Strict mode “use strict”; // yes, it’s just a string bug = 0; // => ReferenceError: bug is not defined • like a built-in JSLint • throws errors instead of ignoring problems • missing in older browsers (IE <10, FF <4)

Slide 30

Slide 30 text

Browser support • Full support in: • IE 9 (strict mode in 10) • FF 4 • Chrome 7 (strict mode in 13) • Opera 12 • Safari 5.1 (bind in 5.1.4) • ... and NodeJS • Compatibility table: http://kangax.github.com/es5-compat-table

Slide 31

Slide 31 text

Shims for older browsers • http://augmentjs.com • https://github.com/ddrcode/ddr-ecma5 • https://github.com/kriskowal/es5-shim • only library extensions, not language extensions (e.g. getters/setters)

Slide 32

Slide 32 text

What’s the point? • more natural and readable (for a Rubyist): list.map(...).forEach(...) vs. _.each(_.map(list, ...), ...) • doesn’t require libraries (except the shim, for now) • future-proof (should still work like this in 2020) • potentially faster if implemented natively

Slide 33

Slide 33 text

let es6 = (es5) => es5 + 1 Coming to a browser near you in 2013-14 (?)