ここ数日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回くらい思い出しては驚いてる気がする