ecmascript 2015 tips & traps

Post on 22-Jan-2018

285 Views

Category:

Software

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

ECMAScript 2015Tips & Traps

Adrian-Tudor Panescu

Iasi, November 2015

Presentation online

https://j.mp/ecmas2015

About me

adrian.panescu.com@adrop

4

5

What’s all about?

● 500+ new features● Backwards-compatible● A much-awaited update (~6 years)● Hopefully the step to a yearly release cycle

6

ES6 or ES2015?

https://twitter.com/JavaScriptDaily/status/662020174837583872

7

Where are we?

Source: https://kangax.github.io/compat-table/es6/05.11.2015

8

Where are we?

https://babeljs.io/ 9

Where are we?

https://twitter.com/JavaScriptDaily/status/660074434821246976

10

Where am I?

● Using ES2015 in production for ~year● 2nd presentation on ES2015 at CodeCamp● Reported Babel and ESLint bugs:

○ https://github.com/babel/babel/issues/2743○ https://github.com/eslint/eslint/issues/3364○ https://github.com/eslint/eslint/issues/3510

11

Tip: arrow functions and this

function Ping() {

this.count = 1;

setInterval(function() {

this.count += 1;

}.bind(this), 16.6);

}

function Ping() {

this.count = 1;

setInterval(() => {

this.count += 1;

}, 16.6);

}

12

Trap: arrow functions and arguments

function foo() {

console.log(arguments);

}

foo(1); // [1]

var foo = () => {

console.log(arguments);

}

foo(1); // ReferenceError

13

Trap: arrow functions and arguments

● Use rest parameters: (...args) => args● Babel uses arguments from enclosing scope (?)

14

Tip: Classes

class Foo {

constructor(bar) {

this.bar = bar;

}

baz() {

return 42;

}

}

var Foo = function(bar) {

this.bar = bar;

}

Foo.prototype.baz = function() {

return 42;

}

15

Trap: forgetting about super()class Foo {

constructor(baz) {

this.baz = baz;

}

}

class Baz extends Foo {

constructor(baz) {

super(baz);

console.log(this.baz);

}

} 16

class Foo {

shout() {

console.log(‘foo!’);

}

}

class Baz extends Foo {

shout() {

super.shout();

console.log(‘baz!’);

}

}

Tip: block scoping

function foo() {

for (var i = 0; i < 2; i++) {

var a = i;

}

console.log(a); // 1

}

function foo() {

for (var i = 0; i < 2; i++) {

let a = i;

}

console.log(a); // ReferenceError

}

17

Trap: Temporal Dead Zone (TDZ)

{

console.log(x); // undefined

var x = ‘codecamp’;

}

{

console.log(x); // ReferenceError

let x = ‘codecamp’;

}

18

Trap: Temporal Dead Zone (TDZ)

Section 13.3.1 in standard (sorry!):

let and const declarations define variables that are scoped to the running execution context’s LexicalEnvironment. The variables are created when their containing Lexical Environment is instantiated but may not be accessed in any way until the variable’s LexicalBinding is evaluated. [...]

19

Trap: Temporal Dead Zone (TDZ)var _temporalUndefined = {};

var x = _temporalUndefined;

function _temporalAssertDefined(val, name, undef) {

if (val === undef) {

throw new ReferenceError(name + " is not defined - temporal dead zone");

}

return true;

}

console.log(_temporalAssertDefined(x, "x", _temporalUndefined) && x);

x = ‘codecamp’;

20Your performance-related concerns: http://kpdecker.github.io/six-speed/

Tip: Iterators/ Generators and for...of

var a = [1, 3, 3, 7];

for (var e of a) {

console.log(e);

}

var a = [1, 3, 3, 7];

var l = a.length;

for (var i = 0; i < l; i++) {

console.log(a[i]);

}

21

Trap: Iterators and constants

var a = [1, 3, 3, 7];

for (const e of a) {

console.log(e);

}

var a = [1, 3, 3, 7];

var l = a.length;

for (const i = 0; i < l; i++) {

console.log(a[i]);

}

22http://stackoverflow.com/questions/31987465/ecmascript-2015-const-in-for-loops

Trap: Iterators and constants

for (const e of a) {

console.log(e);

}

const it = a[Symbol.iterator]();

let res;

while (res = it.next() && !res.done) {

const e = __res.value;

console.log(e);

}

23http://stackoverflow.com/questions/31987465/ecmascript-2015-const-in-for-loops

Tip: Promises

xhr(‘https://foo.com/’

function(resp) {

readHTML(resp,

function(html) {},

function(err) {})

},

function(err) {}

);

xhr(‘https://foo.com/’)

.then(readHTML)

.then(function(html) {})

.catch(function(err) {});

24

Tip: Promises

function xhr(url) {

return new Promise(function(resolve, reject) {

try {

// do some async work then...

resolve(data);

} catch(e) {

// if something goes wrong...

reject(e);

}

});

}25

Trap: forgetting to return

xhr(‘https://foo.com/’)

.then((data) => {

readHTML(data);

})

.then((html) => {

console.log(html); // nope

}

.catch(console.error.bind(console));

xhr(‘https://foo.com/’)

.then((data) => {

return readHTML(data);

})

.then((html) => {

console.log(html); // okay

}

.catch(console.error.bind(console));

26

Trap: passing a non-function to .then()

xhr(‘https://foo.com/’)

.then(readHTML())

.then((result) => {

// XHR response

});

xhr(‘https://foo.com/’)

.then(readHTML)

.then((result) => {

// HTML response

});

27

Trap: .then(resolve, reject)

xhr(‘https://foo.com’)

.then(() => {

throw new ReferenceError;

}

.catch((err) => {

// never gonna give you up

console.log(err);

});

xhr(‘https://foo.com’)

.then(() => {

throw new ReferenceError;

},

(err) => {

// oblivious

console.log(err);

});

28

Trap: Array.forEach vs. Promises

getURLs()

.then((urls) => {

return

urls.forEach(readHTML);

})

.then(() => {

console.log(‘all urls read?’);

})

.catch(console.error.bind(console));

getURLs()

.then((urls) => {

return

Promise.all(urls.map(readHTML);

})

.then(() => {

console.log(‘all urls read!’);

})

.catch(console.error.bind(console));

29

Tip: Promise-driven architecture

function foo() {

return 42;

}

function foo() {

return Promise.resolve(42);

}

30

Tip: Reflect.apply

a = [99, 111, 100, 101, 99, 97, 109, 112];

String.fromCharCode.apply(null, a);

String.fromCharCode.call(null, a[0], a[1]));

a = [99, 111, 100, 101, 99, 97, 109, 112];

Reflect.apply(String.fromCharCode, null, a);

31

Trap: Reflect.apply expects an array

let a = [‘hello’, ‘world’]

Reflect.apply(

e => console.log(e), null, a);

let a = [‘hello’, ‘world’]

Reflect.apply(

e => console.log(e), null, [a]);

Reflect.apply(console.log, console, a);

32

Tip: simple things

delete foo[‘bar’]

parseInt(‘1337’, 10)

Reflect.deleteProperty(foo, ‘bar’)

Number.parseInt(‘1337’, 10)

33

Fin

● ECMAScript 2015 brings many nice features● Solves some of ES5’s strangeness

○ Hopefully we won’t have to revisit “The Good Parts”● Browsers should really start catching up

○ Babel is here to stay○ Transpilers will always have a performance handicap

● We had 5 ReferenceErrors

34

top related