ES6について

7 minute read

Overview

https://github.com/lukehoban/es6features#readme

http://help.wtf/es6

http://es6-features.org

String

String.x is deprecated; use String.prototype.x instead.

非推奨の構文:

1var num = 15; 
2String.replace(num, /5/, '2');

標準の構文:

1var num = 15;
2String(num).replace(/5/, '2');

Template literal

Nesting templates:

1const classes = `header ${ isLargeScreen() ? '' : `icon-${item.isCollapsed ? 'expander' : 'collapser'}` }`;

タグ付けされたtemplate

 1var a = 5;
 2var b = 10;
 3
 4function tag(strings, ...values) {
 5  console.log(strings[0]); // "Hello "
 6  console.log(strings[1]); // " world"
 7  console.log(values[0]);  // 15
 8  console.log(values[1]);  // 50
 9
10  return "Bazinga!";
11}
12
13tag`Hello ${ a + b } world ${ a * b}`;
14// "Bazinga!"

http://help.wtf/es6#template_literals

 1// Backticks enclose a template literal; ${} interpolates arbitrary expressions
 2let num = 99; // see block scope
 3console.log(`${num} bottles of beer on the wall, ${num} bottles of beer
 4Take one down and pass it around, ${--num} bottles of beer!`);
 5
 6// Tagged form: Attach a function that processes string fragments and evaluated
 7// expressions
 8function celsius(strings, ...values) {
 9  let rv = '';
10  strings.forEach((string, index) => { // See arrow functions
11    rv += string;
12    if (typeof values[index] !== 'undefined')
13      rv += Math.round((values[index] - 32) / 1.8);
14  });
15  return rv;
16}
17
18// Converts all the interpolated numbers to the proper unit
19console.log(celsius `Today temperatures ranged from ${60} to ${65} degrees.`);

var and let

https://eslint.org/docs/rules/no-var

ECMAScript 6 allows programmers to create variables with block scope instead of function scope using the let and const keywords. Block scope is common in many other programming languages and helps programmers avoid mistakes.

1if (true) {
2    var i = 1;
3    let j = 2;
4}
5
6console.log(i) // 1
7console.log(j) // ReferenceError: not defined

Default function parameters

1function multiply(a, b = 1) {
2  return a * b;
3}

Iterators and for…of

 1let fibonacci = {
 2  [Symbol.iterator]() {
 3    let pre = 0, cur = 1;
 4    return {
 5      next() {
 6        [pre, cur] = [cur, pre + cur];
 7        return { done: false, value: cur }
 8      }
 9    }
10  }
11}
12
13for (var n of fibonacci) {
14  // truncate the sequence at 1000
15  if (n > 1000)
16    break;
17  console.log(n);
18}

More: Duck Typing

Modules

import and export

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export

Module Loaders

Module loaders support:

  • Dynamic loading
  • State isolation
  • Global namespace isolation
  • Compilation hooks
  • Nested virtualization

The default module loader can be configured, and new loaders can be constructed to evaluate and load code in isolated or constrained contexts.

 1// Dynamic loading – ‘System’ is default loader
 2System.import('lib/math').then(function(m) {
 3  alert("2π = " + m.sum(m.pi, m.pi));
 4});
 5
 6// Create execution sandboxes – new Loaders
 7var loader = new Loader({
 8  global: fixup(window) // replace ‘console.log’
 9});
10loader.eval("console.log('hello world!');");
11
12// Directly manipulate module cache
13System.get('jquery');
14System.set('jquery', Module({$: $})); // WARNING: not yet finalized

Promises

JavaScript Promiseの本

 1function asyncFunction() {
 2    
 3    return new Promise(function (resolve, reject) {
 4        setTimeout(function () {
 5            resolve('Async Hello world');
 6        }, 16);
 7    });
 8}
 9
10asyncFunction().then(function (value) {
11    console.log(value);    // => 'Async Hello world'
12}).catch(function (error) {
13    console.error(error);
14});

Generators

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols

 1// A generator function will return an object that implements the iteration
 2// protocol, i.e., it has a next() method that returns
 3// { value: < some value>, done: <true or false> }
 4function* incRand(max) { // Asterisk defines this as a generator function
 5  while (true) {
 6    // Pause execution after the yield, resume when next(<something>) is called
 7    // and assign <something> to x
 8    let x = yield Math.floor(Math.random() * max + 1);
 9    max += x;
10  }
11}
12var rng = incRand(2); // Now we have a generator object to work with
13console.log(rng.next()); // { value: <between 1 and 2>, done: false }
14console.log(rng.next(3)); // as above, but between 1 and 5
15console.log(rng.next()); // as above, but NaN since 5 + undefined results in NaN
16console.log(rng.next(20)); // Oops, looks like we broke it! NaN again.
17rng.throw(new Error('Unrecoverable generator state.')); // Will be thrown from yield

shorthand of Object initializer

https://ariya.io/2013/02/es6-and-object-literal-property-value-shorthand

 1// Shorthand property names (ES2015)
 2var a = 'foo', b = 42, c = {};
 3var o = {a, b, c};
 4
 5// Shorthand method names (ES2015)
 6var o = {
 7  property(parameters) {}
 8};
 9
10// Computed property names (ES2015)
11var prop = 'foo';
12var o = {
13  [prop]: 'hey',
14  ['b' + 'ar']: 'there'
15};

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

Destructuring

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

The destructuring assignment syntax is a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables. Destructuring is fail-soft, similar to standard object lookup foo[“bar”], producing undefined values when not found.

1let [n1, n2, n3, n4, ...r] = [100, 'three', 34, {number: 23}, 694, 'eighteen'];
2console.log(n1, n2, n3, n4); // "100 'three' 34 { number: 23 }"
3console.log(r); // "[ 694, 'eighteen' ]"

Two variables values can be swapped in one destructuring expression

1var a = 1;
2var b = 3;
3
4[a, b] = [b, a];
5console.log(a); // 3
6console.log(b); // 1

Object Destructuring

1var o = {p: 42, q: true};
2var {p, q} = o;
3
4console.log(p); // 42
5console.log(q); // true

Works for function parameters

1var fmt = ({id = 0, name}) => `${id}: ${name}`;
2console.log(fmt({ id: 1, name: 'joe'}));

symbol

https://developer.mozilla.org/en-US/docs/Glossary/Symbol

sympol is a primitive data type. The Symbol() function returns a value of type symbol and every returned value is unique. It does not support new Symbol()

1var sym1 = Symbol();
2var sym2 = Symbol('foo');
3var sym3 = Symbol('foo');
4
5Symbol('foo') === Symbol('foo'); // false
6var sym = new Symbol(); // TypeError

Map + Set + WeakMap + WeakSet

Reference: Why WeakMap?

Native WeakMaps hold “weak” references to key objects, which means that they do not prevent garbage collection in case there would be no other reference to the key object. This also avoids preventing garbage collection of values in the map.

 1/ Sets
 2var s = new Set();
 3s.add("hello").add("goodbye").add("hello");
 4s.size === 2;
 5s.has("hello") === true;
 6
 7// Maps
 8var m = new Map();
 9m.set("hello", 42);
10m.set(s, 34);
11m.get(s) == 34;
12
13// Weak Maps
14var wm = new WeakMap();
15wm.set(s, { extra: 42 });
16wm.size === undefined
17
18// Weak Sets
19var ws = new WeakSet();
20ws.add({ data: 42 });
21// Because the added object has no other references, it will not be held in the set

New APIs in core libraries

 1// Number
 2Number.EPSILON
 3Number.isInteger(Infinity) // false
 4Number.isNaN("NaN") // false
 5
 6// Math
 7Math.acosh(3) // 1.762747174039086
 8Math.hypot(3, 4) // 5
 9Math.imul(Math.pow(2, 32) - 1, Math.pow(2, 32) - 2) // 2
10
11// String
12"abcde".includes("cd") // true
13"abc".repeat(3) // "abcabcabc"
14
15// Array
16Array.from(document.querySelectorAll('*')) // Returns a real Array
17Array.of(1, 2, 3) // Similar to new Array(...), but without special one-arg behavior
18[0, 0, 0].fill(7, 1) // [0,7,7]
19[1, 2, 3].find(x => x == 3) // 3
20[1, 2, 3].findIndex(x => x == 2) // 1
21[1, 2, 3, 4, 5].copyWithin(3, 0) // [1, 2, 3, 1, 2]
22["a", "b", "c"].entries() // iterator [0, "a"], [1,"b"], [2,"c"]
23["a", "b", "c"].keys() // iterator 0, 1, 2
24["a", "b", "c"].values() // iterator "a", "b", "c"
25
26// Object
27Object.assign(Point, { origin: new Point(0,0) })

Proxies

The Proxy object is used to define custom behavior for fundamental operations (e.g. property lookup, assignment, enumeration, function invocation, etc).

See more examples at MDN Proxy doc

No-op forwarding proxy

1var target = {};
2var p = new Proxy(target, {});
3
4p.a = 37; // operation forwarded to the target
5
6console.log(target.a); // 37. The operation has been properly forwarded

Validation

 1let validator = {
 2  set: function(obj, prop, value) {
 3    if (prop === 'age') {
 4      if (!Number.isInteger(value)) {
 5        throw new TypeError('The age is not an integer');
 6      }
 7      if (value > 200) {
 8        throw new RangeError('The age seems invalid');
 9      }
10    }
11
12    // The default behavior to store the value
13    obj[prop] = value;
14
15    // Indicate success
16    return true;
17  }
18};
19
20let person = new Proxy({}, validator);
21
22person.age = 100;
23console.log(person.age); // 100
24person.age = 'young'; // Throws an exception
25person.age = 300; // Throws an exception

Binary and Octal Literals

0b111110111 === 503 // true
0o767 === 503 // true

その他

Reflect API

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect

Tail calls

1function factorial(n, acc = 1) {
2    'use strict';
3    if (n <= 1) return acc;
4    return factorial(n - 1, n * acc);
5}
6
7// Stack overflow in most implementations today,
8// but safe on arbitrary inputs in ES6
9factorial(100000)

Unicode

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/unicode