--- title: ES6について date: 2019-01-18 16:00:00 tags: - JavaScript category: tech keywords: - Javascript - ES2015 - ES6 --- ## Overview [https://github.com/lukehoban/es6features#readme](https://github.com/lukehoban/es6features#readme) [http://help.wtf/es6](http://help.wtf/es6) [http://es6-features.org](http://es6-features.org) ## String ### String.x is deprecated; use String.prototype.x instead. 非推奨の構文: ```Javascript var num = 15; String.replace(num, /5/, '2'); ``` 標準の構文: ```Javascript var num = 15; String(num).replace(/5/, '2'); ``` ### Template literal Nesting templates: ```Javascript const classes = `header ${ isLargeScreen() ? '' : `icon-${item.isCollapsed ? 'expander' : 'collapser'}` }`; ``` タグ付けされたtemplate ```Javascript var a = 5; var b = 10; function tag(strings, ...values) { console.log(strings[0]); // "Hello " console.log(strings[1]); // " world" console.log(values[0]); // 15 console.log(values[1]); // 50 return "Bazinga!"; } tag`Hello ${ a + b } world ${ a * b}`; // "Bazinga!" ``` [http://help.wtf/es6#template_literals](http://help.wtf/es6#template_literals) ```Javascript // Backticks enclose a template literal; ${} interpolates arbitrary expressions let num = 99; // see block scope console.log(`${num} bottles of beer on the wall, ${num} bottles of beer Take one down and pass it around, ${--num} bottles of beer!`); // Tagged form: Attach a function that processes string fragments and evaluated // expressions function celsius(strings, ...values) { let rv = ''; strings.forEach((string, index) => { // See arrow functions rv += string; if (typeof values[index] !== 'undefined') rv += Math.round((values[index] - 32) / 1.8); }); return rv; } // Converts all the interpolated numbers to the proper unit console.log(celsius `Today temperatures ranged from ${60} to ${65} degrees.`); ``` ## var and let [https://eslint.org/docs/rules/no-var](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. ```Javascript if (true) { var i = 1; let j = 2; } console.log(i) // 1 console.log(j) // ReferenceError: not defined ``` ## Default function parameters ```Javascript function multiply(a, b = 1) { return a * b; } ``` ## Iterators and for...of ```Javascript let fibonacci = { [Symbol.iterator]() { let pre = 0, cur = 1; return { next() { [pre, cur] = [cur, pre + cur]; return { done: false, value: cur } } } } } for (var n of fibonacci) { // truncate the sequence at 1000 if (n > 1000) break; console.log(n); } ``` More: [Duck Typing](https://en.wikipedia.org/wiki/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/import) [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export](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. ```Javascript // Dynamic loading – ‘System’ is default loader System.import('lib/math').then(function(m) { alert("2π = " + m.sum(m.pi, m.pi)); }); // Create execution sandboxes – new Loaders var loader = new Loader({ global: fixup(window) // replace ‘console.log’ }); loader.eval("console.log('hello world!');"); // Directly manipulate module cache System.get('jquery'); System.set('jquery', Module({$: $})); // WARNING: not yet finalized ``` ## Promises [JavaScript Promiseの本](https://github.com/azu/promises-book) ```Javascript function asyncFunction() { return new Promise(function (resolve, reject) { setTimeout(function () { resolve('Async Hello world'); }, 16); }); } asyncFunction().then(function (value) { console.log(value); // => 'Async Hello world' }).catch(function (error) { console.error(error); }); ``` ## Generators [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) ```Javascript // A generator function will return an object that implements the iteration // protocol, i.e., it has a next() method that returns // { value: < some value>, done: } function* incRand(max) { // Asterisk defines this as a generator function while (true) { // Pause execution after the yield, resume when next() is called // and assign to x let x = yield Math.floor(Math.random() * max + 1); max += x; } } var rng = incRand(2); // Now we have a generator object to work with console.log(rng.next()); // { value: , done: false } console.log(rng.next(3)); // as above, but between 1 and 5 console.log(rng.next()); // as above, but NaN since 5 + undefined results in NaN console.log(rng.next(20)); // Oops, looks like we broke it! NaN again. rng.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](https://ariya.io/2013/02/es6-and-object-literal-property-value-shorthand) ```Javascript // Shorthand property names (ES2015) var a = 'foo', b = 42, c = {}; var o = {a, b, c}; // Shorthand method names (ES2015) var o = { property(parameters) {} }; // Computed property names (ES2015) var prop = 'foo'; var o = { [prop]: 'hey', ['b' + 'ar']: 'there' }; ``` [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment](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. ```Javascript let [n1, n2, n3, n4, ...r] = [100, 'three', 34, {number: 23}, 694, 'eighteen']; console.log(n1, n2, n3, n4); // "100 'three' 34 { number: 23 }" console.log(r); // "[ 694, 'eighteen' ]" ``` Two variables values can be swapped in one destructuring expression ```Javascript var a = 1; var b = 3; [a, b] = [b, a]; console.log(a); // 3 console.log(b); // 1 ``` Object Destructuring ```Javascript var o = {p: 42, q: true}; var {p, q} = o; console.log(p); // 42 console.log(q); // true ``` Works for function parameters ```Javascript var fmt = ({id = 0, name}) => `${id}: ${name}`; console.log(fmt({ id: 1, name: 'joe'})); ``` ## symbol [https://developer.mozilla.org/en-US/docs/Glossary/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()` ```Javascript var sym1 = Symbol(); var sym2 = Symbol('foo'); var sym3 = Symbol('foo'); Symbol('foo') === Symbol('foo'); // false var sym = new Symbol(); // TypeError ``` ## Map + Set + WeakMap + WeakSet Reference: [Why WeakMap?](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap#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. ```Javascript / Sets var s = new Set(); s.add("hello").add("goodbye").add("hello"); s.size === 2; s.has("hello") === true; // Maps var m = new Map(); m.set("hello", 42); m.set(s, 34); m.get(s) == 34; // Weak Maps var wm = new WeakMap(); wm.set(s, { extra: 42 }); wm.size === undefined // Weak Sets var ws = new WeakSet(); ws.add({ data: 42 }); // Because the added object has no other references, it will not be held in the set ``` ## New APIs in core libraries ```Javascript // Number Number.EPSILON Number.isInteger(Infinity) // false Number.isNaN("NaN") // false // Math Math.acosh(3) // 1.762747174039086 Math.hypot(3, 4) // 5 Math.imul(Math.pow(2, 32) - 1, Math.pow(2, 32) - 2) // 2 // String "abcde".includes("cd") // true "abc".repeat(3) // "abcabcabc" // Array Array.from(document.querySelectorAll('*')) // Returns a real Array Array.of(1, 2, 3) // Similar to new Array(...), but without special one-arg behavior [0, 0, 0].fill(7, 1) // [0,7,7] [1, 2, 3].find(x => x == 3) // 3 [1, 2, 3].findIndex(x => x == 2) // 1 [1, 2, 3, 4, 5].copyWithin(3, 0) // [1, 2, 3, 1, 2] ["a", "b", "c"].entries() // iterator [0, "a"], [1,"b"], [2,"c"] ["a", "b", "c"].keys() // iterator 0, 1, 2 ["a", "b", "c"].values() // iterator "a", "b", "c" // Object Object.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]([https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy)) **No-op forwarding proxy** ``` Javascript var target = {}; var p = new Proxy(target, {}); p.a = 37; // operation forwarded to the target console.log(target.a); // 37. The operation has been properly forwarded ``` **Validation** ```Javascript let validator = { set: function(obj, prop, value) { if (prop === 'age') { if (!Number.isInteger(value)) { throw new TypeError('The age is not an integer'); } if (value > 200) { throw new RangeError('The age seems invalid'); } } // The default behavior to store the value obj[prop] = value; // Indicate success return true; } }; let person = new Proxy({}, validator); person.age = 100; console.log(person.age); // 100 person.age = 'young'; // Throws an exception person.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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect) ### Tail calls ```Javascript function factorial(n, acc = 1) { 'use strict'; if (n <= 1) return acc; return factorial(n - 1, n * acc); } // Stack overflow in most implementations today, // but safe on arbitrary inputs in ES6 factorial(100000) ``` ### Unicode [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/unicode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/unicode)