ES6/ES7
Topics
- Arrow function
- Async Await
- Class
- Symbol
- Iterator
- Generator
- Map, Set, WeakMap, WeakSet
https://ponyfoo.com/articles/es6
https://hackernoon.com/es8-was-released-and-here-are-its-main-new-features-ee9c394adf66
http://jamesknelson.com/es6-the-bits-youll-actually-use/
https://ponyfoo.com/articles/tagged/es6-in-depth
http://exploringjs.com/es6/index.html
Symbol
Symbol is new type of primitive value, globally unique, and unguessable value.
To create symbol, you call a function Symbol
var x = Symbol();
You can pass string as a label of your symbol.
var keyName = Symbol("User Name");
// Symbol(User Name)
var keyAge = Symbol("User Age");
Symbol provides meta extendable hook which is called well-known symbols.
Symbol.Iterator
Symbol.toStringTag
Symbol.toPrimitive
Symbol.isConcatSpreadable
Iterator
http://2ality.com/2015/02/es6-iteration.html
Iterable | Iterable has iterator and access it by referring Symbol.iterator as key. String, Array, TypedArray, Map and Set are all built-in iterables, because each of their prototype objects implements an @@iterator method. Object is not iterable by default. |
---|---|
Iterator | iterator is an object has method called next which return iterator result. |
Iterator Result | Iterator Result is an object returned from Iterator and has property value and done. { value: 1, done: false }. If it is end. it returns { value: undefined, done: true }. |
var array = [1, 2, 3]
var iterator = array[Symbol.iterator]()
iterator.next() // { value: 1, done: false}
iterator.next() // { value: 2, done: false}
iterator.next() // { value: 3, done: false}
iterator.next() // { value: undefined, done: true}
spread operator works on iterator and does for ... of
loop underneath.
In order to attest it, you can put an object with spread operator.
var k = { name: 'kei' }
[...k]
// Uncaught TypeError: k is not iterable
You can create custom iterable here.
var obj = {
userIds: [1, 2, 12, 34, 56, 72]
}
obj[Symbol.iterator] = function() {
var index = 0
var iterator = {
next: function() {
var userId = this.userIds[index]
index++
if (index < this.userIds.length) {
return { value: userId, done: false}
} else {
return { value: undefined, done: true}
}
}.bind(this )
}
return iterator
}
var iterator = obj[Symbol.iterator]()
console.log(iterator.next()) // { value: 1, done: false }
console.log(iterator.next()) // { value: 2, done: false }
console.log(iterator.next()) // { value: 12, done: false }
console.log(iterator.next()) // { value: 34, done: false }
console.log(iterator.next()) // { value: 56, done: false }
console.log(iterator.next()) // { value: undefined, done: true }
http://exploringjs.com/es6/ch_iteration.html#sec_iterability
http://2ality.com/2015/02/es6-iteration.html
Generator
Generator produces iterator for you. yield
keyword returns iterator result and assign yield value into value on iterator result.
A GeneratorFunction is a special type of function that works as a factory for iterators. When it is executed it returns a new Generator object. A function becomes a GeneratorFunction if it uses the function* syntax.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators
function* count() {
yield 9
}
var iterator = count() // return iterator
iterator.next() // { value: 9, done: false } <= iterator result
so keyword yield
seems stops the iterator. The lines after yield will not be executed until iterator.next will be invoked.
function* count() {
yield 9
console.log("Hi")
yield 10
console.log("Bye")
}
var iterator = count() // return iterator
iterator.next() // { value: 9, done: false } <= iterator result
console.log(iterator.next())
// { value: 9, done: false }
console.log(iterator.next())
// Hi
// { value: 10, done: false }
console.log(iterator.next())
// Bye
// { value: undefined, done: true }
You can "return" value from generator but it also makes done
property to true which for..of
loop does not catch returned value.
function* count() {
yield 1
yield 2
return3
}
var it = count()
it.next() // { value: 1, done: false }
it.next() // { value: 2, done: false }
it.next() // { value: 3, done: true }
for (let num of it) {
console.log(num)
}
// 1
// 2
// won't print 3 because iterator result returns `done:true`
https://davidwalsh.name/es6-generators
Map and Set (WeakMap, WeakSet)
Map and Set is new data structure on ES6.
Map is key-value pair collection
var person = new Map()
person.set('name', 'Kei')
person.set('age', 28)
// We can pass an array as well
var person = new Map([
['name', 'Kei'],
['age', 28]
])
Set is value collection
Why Map is needed over Object?
Object | Map | |
---|---|---|
Delete | delete person.name | person |
JSON support | Yes | No |
Iterable (built-in) | No | Yes |
key | string or integer | Anything |
Memory Usage | 5 times more |
Use maps over objects when keys are unknown until run time, and when all keys are the same type and all values are the same type.
Use maps in case if there is a need to store primitive values as keys because object treats each key as a string whether it's a number value, boolean value or any other primitive value.
Use objects when there is logic that operates on individual elements.
Object is key-value
Why Set is needed over Array?
- Map is iteratable, Object is not. (Object can have iterator)
Proxies
Proxy allows us to write code in "reflective meta programming" way.
The definition of reflective meta programming is..
Introspection: you have read-only access to the structure of a program.
Self-modification: you can change that structure.
Intercession: you can redefine the semantics of some language operations.
Proxy as "wrapping" the target object. In that sense, the proxy becomes the primary object that the code interfaces with, and the actual target object remains hidden/protected. It is meta programming of javascript and change behavior of an object.
A proxy can become the prototype of an object. Some operations that begin in an object may continue in proxy.
validation
value correction
property lookup extensions
tracing property accesses
revocable references
implementing the DOM in javascript
Here is example.
var target = {}
var handler = {
get: function() {
return "Hello"
}
}
var proxy = new Proxy(target, handler);
proxy.test // Hello
Proxy revocable
Proxy revocable generates proxy object without new keyword and return proxy
object and revoke
function.
let { proxy, revoke } = Proxy.revocable(target, handler);
Example
https://github.com/solkimicreb/react-easy-state
https://github.com/eiriklv/json-populate
https://www.sitepoint.com/es6-proxies/
Reading Material
https://www.youtube.com/watch?v=nsG_izwv_0U
https://www.youtube.com/watch?v=LkV-zr4HTjY
https://www.youtube.com/watch?v=opf7xX-whIw
https://www.youtube.com/watch?v=_5X2aB_mNp4
http://www.zsoltnagy.eu/es6-proxies-in-practice/
https://hacks.mozilla.org/2015/07/es6-in-depth-proxies-and-reflect/
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect
http://2ality.com/2014/12/es6-proxies.html
Reflect
Unlike most global objects,Reflect
is not a constructor. You can not use it with anew
operator or invoke theReflect
object as a function. All properties and methods ofReflect
are static (just like theMath
object)
Reflect traps are same as proxy handlers.
get
set
apply
Reflect.get()
Reflect.set()
Reflect.apply()