ES6 - ECMAScript2015

日本語 : エクマススクリプト

arrow function

When an arrow function is written without block braces, with or without multiple parameters, the expression that constitutes the function's body is implicitly returned 애로우 펑션을 블록이 없게 사용하는 경우 function의 body를 암묵적으로 리턴한다.

return

The return statement is implicitly added.

curried function

連続の複数のarrow functionを利用する形?

handleChange = field => e => {
    e.preventDefault();
}

Syntax

// Basic syntax / 基本syntax :
(param1, param2, paramN) => { statements }
(param1, param2, paramN) => expression
   // equivalent to:  => { return expression; }
   // returnが自動でつく

// Parentheses are optional when there's only one argument:
// argumentがひとつの場合には[]波かっこはoption
singleParam => { statements }
singleParam => expression

// A function with no arguments requires parentheses:
() => { statements }

// Advanced:
// Parenthesize the body to return an object literal expression:
params => ({foo: bar})

// Rest parameters are supported
(param1, param2, ...rest) => { statements }

Shorter function

var a = [
  "Hydrogen",
  "Helium",
  "Lithium",
  "Beryl­lium"
];

// old
var a2 = a.map(function(s){ return s.length});
// new
var a3 = a.map(s => s.lenght) // s.length を自動でreturnする

let

  • let is block-scoped, it only exists within the current block.
  • var is function-scoped.

const

letと似っている const is quite similar to let.

  • const is also block-scoped
  • const also enjoys the marvels of TDZ semantics

There’s also a couple of major differences.

  • const variables must be declared using an initializer
  • const variables can only be assigned to once, in said initializer
  • const variables don’t make the assigned value immutable
  • Assigning to const will fail silently
  • Redeclaration of a variable by the same name will throw

一度assignされたら変更できないが、

const cool = { people: ['you', 'me', 'tesla', 'musk'] }
cool = {}
// <- "cool" is read-only

完全にimmutableではない

const cool = { people: ['you', 'me', 'tesla', 'musk'] }
cool.people.push('berners-lee')
console.log(cool)
// <- { people: ['you', 'me', 'tesla', 'musk', 'berners-lee'] }


// You can also make other references to the const that can, in fact, change.

const cool = { people: ['you', 'me', 'tesla', 'musk'] }
var uncool = cool
uncool = { people: ['edison'] } // so uncool he's all alone
console.log(uncool)
// <- { people: ['edison'] }

完全にimmutableにするためには

Hoisting

https://hacks.mozilla.org/2015/07/es6-in-depth-let-and-const/?utm_source=javascriptweekly&utm_medium=email

The scope of a var in JavaScript is like the bucket-of-paint tool in Photoshop. It extends in both directions from the declaration, forwards and backwards, and it just keeps going until it reaches a function boundary. Since this variable t’s scope extends so far backwards, it has to be created as soon as we enter the function. This is called hoisting. I like to imagine the JS engine lifting each var and function to the top of the enclosing function with a tiny code crane.

decorator - Javaのannotationみたいな

symbol

sym1 = Symbol()
sym2 = Symbol('name')

#typeof演算子で評価すると"symbol"が返される
typeof sym1  // "symbol"


new Symbol()  // TypeError

symobj = Object(sym2)
typeof symobj  // "object"

by object property

var foo = Symbol();
var hoge[foo] = {}

hoge[foo] // 5
hoge.foo // undefined
hoge['foo'] // undefined
  • 一旦作ったシンボルは、それ自身とのみ等しくなる、ユニークなIDとして機能する。( === や == で評価して true になるものを、後から再生成することはできない。)そういう意味ではオブジェクトに似ている
  • シンボルはオブジェクトのプロパティキーとして使用できる(そういう意味では文字列に似ている)。
    • つまりvar foo = Symbol(); hoge[foo] = 5; というコードが動作する(これは hoge.foo = 5 つまり hoge['foo'] = 5 とは全く別物)

example

列挙・定数

const LOG_LEVEL_INFO = Symbol('log_level_info');
const LOG_LEVEL_WARN = Symbol('log_level_warn');

var suits = {
  HEART: Symbol('heart'),
  DIAMOND: Symbol('diamond'),
  SPADE: Symbol('spade'),
  CLUB: Symbol('club')
};

短所

JSONと相性が悪いこと。現状、JSON.stringify() はシンボル(キー側にあっても値側にあっても)を完全に無視してしまう。今でもreplacerで頑張れば部分的にはなんとかできるが、個人的にはまだ使いたくない。

DOMにプライベート情報を保存

ライブラリ作者などがDOM要素に一時データを保存したい場合、これまでは他のライブラリとの名前の衝突を防ぐため、 __mylib_private_isHogehoge のような、他のライブラリと干渉しないであろうユニークなキー名を使うなどしてしのいでいたが、シンボルを使えばそれがエレガントになるし、デバッグも少ししやすいかもしれない

 // こうする代わりに
var isChecked = 'mylib_private_isChecked_j8z54eomjlcz';
domElement[isChecked] = true;

// シンボルを使えば、絶対に他人と衝突しない
var isChecked = Symbol('isChecked');
domElement[isChecked] = true;

注意

  • Symbols and for...in iteration
  • Symbols and JSON.stringify()

symbol reference

proto

  • proto はすべてのオブジェクトが持つプロパティ
  • Object.prototype (すべてのオブジェクトの元) の proto には null が入っている
  • new したときに、コンストラクタの prototype への参照(アドレス)を格納する
  • proto には prototype のアドレスが格納されている。prototype は proto のアドレスを参照し、プロトタイプチェーンが実現している。
  • 最上位の Object.prototype.proto までプロパティを探索する
  • Object.prototype の proto は null
  • new でインスタンスを生成したとき、関数(コンストラクタ)の prototype へのアドレスを格納する
function SampleA() {}
SampleA.prototype.a = 'a';
console.log( SampleA.prototype.__proto__ );

var SampleB = function() {}
SampleB.prototype = new SampleA();
console.log( SampleB.prototype.__proto__ );

var sample_obj = new SampleB();
console.log( sample_obj.__proto__ );

console.log( sample_obj.__proto__.a );
Object
SampleA
SampleA
a

prototypeについて

prototype とは、関数オブジェクトが定義された時点で自動的に作成されるメンバ変数です

string

Rest Parameter

function concat (...words) {
  return words.join(' ')
}
var result = concat('this', 'is', 'okay')
console.log(result)
// <- 'this is okay'

Spread Operator

function concat(...words) {
    return words.join(' ')
}
var result = concat('this', 'is', 'okay')
console.log(result);
Use Case ES5 ES6
Concatenation [1, 2].concat(more) [1, 2, ...more]
Push onto list list.push.apply(list, [3, 4]) list.push(...[3, 4])
Destructuring a = list[0], rest = list.slice(1) [a, ...rest] = list
new + apply new (Date.bind.apply(Date, [null,2015,31,8])) new Date(...[2015,31,8])

Generator

  • generator functionは function*で宣言する
  • function*で宣言されたfunctionはgeneratorをreturnする
  • yieldを使ったfunctionがfunction*つまり、*がない場合にはエラーになる
  • generator functionは任意の時点で処理を中断/再開することができる関数
    • Generators are functions which can be exited and later re-entered. Their context (variable bindings) will be saved across re-entrances.(from mdn)

generatorを理解するための3つのキーワード

  • Generator Function
    • 処理の中断/再開が行われる特殊な関数
    • function* generatorFunction(){}のようにfunction*を使って定義する
  • Generator Object
    • 中断された処理を再開したり、値を取得し対するオブジェクト
    • var generatorObject = generatorFunction()のように取得する
  • yield
    • Generator Functionの中で使われる処理の中断を指定するキーワード
    • var result = yield request('http://example.com')のように使う

references for generator

Object initializer (object初期化)

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Object_initializer

ECMAScript第6版での新しい表記法

  • Shorthand property names
  • Shorthand method names
  • Computed property names
    • これはvuexのmutation function name定義にも利用されている
// Shorthand property names (ES6)
var a = "foo", b = 42, c = {};
var o = { a, b, c };

// Shorthand method names (ES6)
var o = {
  property([parameters]) {},
  get property() {},
  set property(value) {},
  * generator() {}
};

// Computed property names (ES6)
var prop = "foo";
var o = {
  [prop]: "hey",
  ["b" + "ar"]: "there",
};

Arrays

First, Array.from creates Array instances from array-like and iterable objects. Examples of array-like objects include:

Array.from

let itemElements = document.querySelectorAll('.items');
let items = Array.from(itemElements);
items.forEach(function(element) {
    console.log(element.nodeType)
});

// A workaround often used in ES5:
let items = Array.prototype.slice.call(itemElements);

An interesting feature of Array.from is the second optional mapFunction argument. This allows you to create a new mapped array in a single invocation:

let navElements = document.querySelectorAll('nav li');
let navTitles = Array.from(navElements, el => el.textContent);

Array.of

let x = new Array(3); // [undefined, undefined, undefined]
let y = Array.of(8); // [8]
let z = [1, 2, 3]; // Array literal

find, findIndex, fill

[5, 1, 10, 8].find(n => n === 10) // 10

[5, 1, 10, 8].findIndex(n => n === 10) // 2

[0, 0, 0].fill(7) // [7, 7, 7]
[0, 0, 0, 0, 0].fill(7, 1, 3) // [0, 7, 7, 7, 0]

Other tips

lodashを使わなくても実装できるes6 method

Object.assign & lodash._assign

これはなからずチェックしておくこと。 めっちゃつかう。

Syntax

Object.assign(target, ...sources)

Feature

  • Cloning an object
    • sources objectを値をcopyしてtarget objectを変更する。
    • なので新しいobjectをreturnしたい場合にはObject.assign({}, source_obj);このように
    • targetにmergeしたい場合にはvar merged_target_obj = Object.assign(target_obj, source_obj);にする
  • Merging objects
  • Copying symbol-typed properties
    • symbolもいける
  • Inherit properties and non-enumerable properties cannot be copied
    • 継承したプロパティとnon-enumerableプロパティはcopyされない
  • Primitives will be wrapped to objects
    • primitive系はobjectにラップされる
    • null and undefinedは無視される
  • Exceptions will interrupt the ongoing copying task
  • Copying accessors

Inherit properties and non-enumerable properties cannot be copied

var obj = Object.create({ foo: 1 }, { // foo is an inherit property.
  bar: {
    value: 2  // bar is a non-enumerable property.
  },
  baz: {
    value: 3,
    enumerable: true  // baz is an own enumerable property.
  }
});

var copy = Object.assign({}, obj);
console.log(copy); // { baz: 3 }

Primitives will be wrapped to objects

var v1 = '123';
var v2 = true;
var v3 = 10;
var v4 = Symbol('foo')

var obj = Object.assign({}, v1, null, v2, undefined, v3, v4);
// Primitives will be wrapped, null and undefined will be ignored.
// Note, only string wrappers can have own enumerable properties.
console.log(obj); // { "0": "1", "1": "2", "2": "3" }

References

results matching ""

    No results matching ""