ここ数日esprimaで遊んでる。
esprima.parse() や estraverse.traverse() では、ASTを取得し、nodeのtypeで処理を分けるんだけど、やりたい事をやるのにどのnodeをチェックすればいいのかわからない。
例えば、コード中で var x = 1; とすべき所を x = 1; としてしまってグローバル変数が出来てしまうのを検出したい時に、 AssignmentExpression だけチェックすれば良いのか?となる。
nodeのtypeは esprima.Syntax で見れる。
また、あるnodeを取得したい時にどんなコードを書けばよいのかは、esprimaのfixture見ればわかる。
本当はEcmaScriptの仕様見た方が良いんだろうけど、すぐ読める気がしない。 なので、fixture見ながら、REPLでポチポチやって、各nodeの特徴をメモしていった。
(半分くらい書いて気づいたけど、ES6独自のnode以外はMDN見れば良いようだった……)
Parser API - Mozilla | MDN
↓↓↓↓↓メモ本文はこちらになります↓↓↓↓↓
↑↑↑↑↑メモ本文はこちらになります↑↑↑↑↑
メモる過程で気づいたこと
言語仕様を軽くおさらいする良い機会になった。
幾つか気づいた事があったのでメモ。
new する時にカッコ必要ない
コンストラクタが引数とらないとき、new A() のカッコを省略できる
> new Date(); Mon Jul 13 2015 11:31:55 GMT+0900 (JST) > new Date; Mon Jul 13 2015 11:31:56 GMT+0900 (JST)
generator の delegate ば便利
同期的にコードが書けるということで大好評のgeneratorですが、delegateって機能使うと更に便利という事がわかった。
[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function#Example_with_yield:title]
↑からコード抜粋
function* anotherGenerator(i) {
yield i + 1;
yield i + 2;
yield i + 3;
}
function* generator(i){
yield i;
yield* anotherGenerator(i);
yield i + 10;
}
var gen = generator(10);
console.log(gen.next().value); // 10
console.log(gen.next().value); // 11
console.log(gen.next().value); // 12
console.log(gen.next().value); // 13
console.log(gen.next().value); // 20
まじか!!!!!!便利!!!!! !!!!!!
日本語の解説記事は無いみたいだった。
ちゃんと英語の情報チェックしなきゃ〜〜
{a:1} はObjectではない??
> esprima.parse('{a:1}').body[0]
{ type: 'BlockStatement',
body: [ { type: 'LabeledStatement', label: [Object], body: [Object] } ] }
> esprima.parse('a = {a:1}').body[0]
{ type: 'ExpressionStatement',
expression:
{ type: 'AssignmentExpression',
operator: '=',
left: { type: 'Identifier', name: 'a' },
right: { type: 'ObjectExpression', properties: [Object] } } }
{a:1} とだけ書いた時はLabeledStatementと判断されてる。
ES6で new.target が追加される
ES6では全てのfunctionが new.target を持つようになる。
これによって、class Child extends Parent {}; new Child(); とした時に、Parentのコンストラクタ内でChildのコンストラクタを取得できるようになる、のかな?
http://www.2ality.com/2015/02/es6-classes-final.html#allocating_and_initializing_the_instance_object
うーんムズそう
LabeledStatement
ループにラベルをつけて、breakやcontinueで指定することで、ネストしたループを抜けたり出来る
a: while (1) { b: while (1) { console.log('b'); break a; } console.log('a'); } // b
この機能ほぼ使わないからすぐ忘れてて、毎年3回くらい思い出しては驚いてる気がする