ES6の新機能CoffeeScriptConvertの展望

公開: 2022-03-11

私はCoffeeScriptのファンで2年以上になります。 私はCoffeeScriptを書く方が生産的で、ばかげた間違いを少なくし、ソースマップのサポートによりCoffeeScriptコードのデバッグは完全に苦痛がないことがわかりました。

ES6の新機能CoffeeScriptConvertの展望

最近、私はBabelを使ってES6で遊んでいますが、全体的にはファンです。 この記事では、CoffeeScript変換の観点から、ES6に関する調査結果をまとめ、気に入っている点を確認し、まだ不足している点を確認します。

構文的に重要なインデント:ブーンまたはベイン?

私は常に、CoffeeScriptの構文的に重要なインデントと少しの愛/憎しみの関係を持っていました。 すべてがうまくいくと、「見て、手を使わないで!」と表示されます。 そのような超ミニマルな構文を使用することの自慢する権利。 しかし、物事がうまくいかず、間違ったインデントが本当のバグを引き起こす場合(私を信じてください、それは起こります)、利益が価値があるとは感じません。

 if iWriteCoffeeScript if iAmNotCareful badThings = 'happen'

通常、これらのバグは、ネストされたステートメントがいくつかあるコードブロックがあり、誤って1つのステートメントを誤ってインデントした場合に発生します。 はい、それは通常、目の疲れが原因ですが、私の意見では、CoffeeScriptで発生する可能性がはるかに高くなります。

ES6を書き始めたとき、腸の反応がどうなるかよくわかりませんでした。 中かっこを再び使い始めるのは本当にいい気分でした。 最新のエディターを使用することも役立ちます。通常、ブレースを開くだけで、エディターは親切にそれを閉じることができます。 CoffeeScriptのブードゥーの魔法の後で、穏やかで澄んだ宇宙に戻ったような気がしました。

 if (iWriteES6) { if (iWriteNestedStatements) { let badThings = 'are less likely to happen' } }

もちろん、私はセミコロンを捨てることを主張します。 私たちがそれらを必要としないならば、私はそれらを捨てると言います。 私はそれらが醜いと思います、そしてそれは余分なタイピングです。

クラスサポート

ES6でのクラスのサポートは素晴らしく、CoffeeScriptから移行する場合は、自宅にいるように感じるでしょう。 簡単な例を使用して、2つの構文を比較してみましょう。

ES6クラス

class Animal { constructor(numberOfLegs) { this.numberOfLegs = numberOfLegs } toString() { return `I am an animal with ${this.numberOfLegs} legs` } } class Monkey extends Animal { constructor(bananas) { super(2) this.bananas = bananas } toString() { let superString = super.toString() .replace(/an animal/, 'a monkey') return `${superString} and ${this.bananas} bananas` } }

CoffeeScriptクラス

class Animal constructor: (@numberOfLegs) -> toString: -> "I am an animal with #{@numberOfLegs} legs" class Monkey extends Animal constructor: (@numberOfBananas) -> super(2) toString: -> superString = super.toString() .replace(/an animal/, 'a monkey') "#{superString} and #{@numberOfLegs} bananas"

第一印象

最初に気付くかもしれないのは、ES6はまだCoffeeScriptよりもはるかに冗長であるということです。 CoffeeScriptで非常に便利なショートカットの1つは、コンストラクターでのインスタンス変数の自動割り当てのサポートです。

 constructor: (@numberOfLegs) ->

これは、ES6の次の機能と同等です。

 constructor(numberOfLegs) { this.numberOfLegs = numberOfLegs }

もちろん、それは実際には世界の終わりではありません。どちらかといえば、このより明示的な構文の方が読みやすいです。 もう1つ欠けている小さな点は、これに対する@ショートカットがないことです。 thisは、Rubyのバックグラウンドから来ると常にいい感じでしたが、これも大したことではありません。 一般的に、私たちはここでかなりくつろいでいます、そして私は実際にメソッドを定義するためにES6構文を好みます。

なんて素晴らしい!

ES6でのsuperの処理方法には小さな落とし穴があります。 CoffeeScriptはRubyの方法でsuperを処理します(「同じ名前のスーパークラスメソッドにメッセージを送信してください」)が、ES6で「ネイキッド」スーパーを使用できるのはコンストラクターだけです。 ES6は、 superがスーパークラスインスタンスへの参照である、より一般的なJavaのようなアプローチに従います。

私は戻ります

CoffeeScriptでは、暗黙のリターンを使用して、次のような美しいコードを作成できます。

 foo = -> if Math.random() > 0.5 if Math.random() > 0.5 if Math.random() > 0.5 "foo"

ここでは、 foo()を呼び出したときに「foo」が返される可能性はほとんどありません。 ES6にはこれがなく、 returnキーワードを使用して戻るように強制されます。

 const foo = () => { if (Math.random() > 0.5 ) { if (Math.random() > 0.5 ) { if (Math.random() > 0.5 ) { return "foo" } } } }

上記の例でわかるように、これは一般的には良いことですが、それでも追加するのを忘れて、予期しない未定義のリターンがいたるところに表示されます。 私が遭遇した例外が1つあります。これは、Arrow Functionsに関して、次のような1つのライナーに対して暗黙のリターンを取得する場合です。

 array.map( x => x * 10 )

これはちょっと便利ですが、中括弧を追加するとreturnが必要になるため、少し混乱する可能性があります。

 array.map( x => { return x * 10 })

ただし、それでも意味があります。 中括弧を追加したのは、複数の行を使用したいためであり、複数の行がある場合は、何を返すのかを明確にするのが理にかなっているからです。

ES6クラス構文ボーナス

CoffeeScriptには、クラスの定義に関していくつかの構文上のトリックがありますが、ES6にも独自のトリックがいくつかあります。

ゲッターとセッター

ES6は、次の例に示すように、ゲッターとセッターを介したカプセル化を強力にサポートしています。

 class BananaStore { constructor() { this._bananas = [] } populate() { // fetch our bananas from the backend here } get bananas() { return this._bananas.filter( banana => banana.isRipe ) } set bananas(bananas) { if (bananas.length > 100) { throw `Wow ${bananas.length} is a lot of bananas!` } this._bananas = bananas } }

ゲッターのおかげで、 bananaStore.bananasにアクセスすると、熟したバナナのみが返されます。 CoffeeScriptの場合、 bananaStore.getBananas()のようなgetterメソッドを介してこれを実装する必要があるため、これは本当に素晴らしいことです。 JavaScriptでプロパティに直接アクセスすることに慣れている場合、これはまったく自然なことではありません。 また、プロパティごとにどのようにアクセスするかを考える必要があるため、開発が混乱します。それは.bananas 、それともgetBananas()ですか。

上記のおもちゃの例に示すように、データセットをクリーンアップしたり、無効なデータが設定されたときに例外をスローしたりできるため、セッターも同様に役立ちます。 これは、Rubyのバックグラウンドを持つ人なら誰でもよく知っているでしょう。

個人的には、これはすべてにゲッターとセッターを使用して夢中になるべきだとは思いません。 (上記の例のように)ゲッターとセッターを介してインスタンス変数をカプセル化することで何かを得ることができる場合は、先に進んでください。 しかし、 isEditableなどのブールフラグがあると想像してください。 isEditableプロパティを直接公開しても何も失われないのであれば、これが最も簡単なアプローチであると私は主張します。

静的メソッド

ES6は静的メソッドをサポートしているため、このいたずらなトリックを実行できます。

 class Foo { static new() { return new this } }

これで、 new Foo()を作成するのが嫌いな場合は、 Foo.new()を作成できます。 newは予約語であるため、純粋主義者は不平を言うでしょうが、非常に簡単なテストの後、Node.jsと最新のブラウザーで問題なく動作するようです。 しかし、おそらくこれを本番環境で使用したくないでしょう!

残念ながら、ES6では静的プロパティがサポートされていないため、クラス定数を定義して静的メソッドでそれらにアクセスする場合は、次のような操作を行う必要があります。これは少しハックです。

 class Foo { static imgPath() { return `${this.ROOT_PATH}/img` } } Foo.ROOT_PATH = '/foo'

宣言型のインスタンスとクラスのプロパティを実装するためのES7プロポーザルがあります。これにより、次のようなことができます。

 class Foo { static ROOT_PATH = '/foo' static imgPath() { return `${this.ROOT_PATH}/img` } }

これは、CoffeeScriptですでに非常にエレガントに実行できます。

 class Foo @ROOT_PATH: '/foo' @imgPath: -> @ROOT_PATH

文字列補間

ついにJavascriptで文字列補間ができるようになりました!

 `I am so happy that in the year ${new Date().getFullYear()} we can interpolate strings`

CoffeeScript / Rubyから来ているので、この構文は少し厄介な感じがします。 おそらく、システムコマンドを実行するためにバックティックが使用されている私のRubyのバックグラウンドのために、最初はかなり間違っていると感じます。 また、ドル記号を使用すると、80年代のように感じますが、それは私だけかもしれません。

下位互換性の懸念から、CoffeeScriptスタイルの文字列補間を実装することはできなかったと思います。 "What a #{expletive} shame"

矢印機能

CoffeeScripterでは矢印関数は当然のことと見なされています。 ES6は、CoffeeScriptのファットアロー構文をほぼ実装しました。 したがって、短い構文が得られ、 thisを字句スコープで取得できるため、ES5を使用するときにこのようなフープをジャンプする必要はありません。

 var that = this doSomethingAsync().then( function(res) { that.foo(res) })

ES6での同等のものは次のとおりです。

 doSomethingAsync().then( res => { this.foo(res) })

単項コールバックの周りの括弧を省略したことに注意してください。

ステロイドのオブジェクトリテラル

ES6のオブジェクトリテラルには、パフォーマンスが大幅に向上しています。 最近はいろいろなことができます!

動的プロパティ名

この記事を書くまで、CoffeeScript1.9.1以降でこれを実行できることに気づきませんでした。

 dynamicProperty = 'foo' obj = {"#{dynamicProperty}": 'bar'}

これは、以前に必要だったこのようなものよりもはるかに痛みが少ないです:

 dynamicProperty = 'foo' obj = {} obj[dynamicProperty] = 'bar'

ES6には、かなり良いと思う代替構文がありますが、大きなメリットはありません。

 let dynamicProperty = 'foo' let obj = { [dynamicProperty]: 'bar' }

ファンキーなショートカット

これは実際にはCoffeeScriptから取得したものですが、これまで私が知らなかったものでした。 それはとにかく非常に便利です:

 let foo = 'foo' let bar = 'bar' let obj = { foo, bar }

これで、 objの内容は{ foo: 'foo', bar: 'bar' }なります。 これは非常に便利で、覚えておく価値があります。

クラスでできることはすべて私にもできる!

オブジェクトリテラルは、次のような場合でも、クラスが実行できるほとんどすべてのことを実行できるようになりました。

 let obj = { _foo: 'foo', get foo() { return this._foo }, set foo(str) { this._foo = str }, isFoo() { return this.foo === 'foo' } }

なぜあなたがそれを始めたいのかよくわかりませんが、ねえ、今あなたはそうすることができます! もちろん、静的メソッドを定義することはできません…それはまったく意味がないからです。

あなたを混乱させるForループ

ES6のfor-loop構文は経験豊富なCoffeeScripterにいくつかの素晴らしい筋肉記憶のバグを導入します。これは、ES6のfor-ofがCoffeeSCriptのfor-inに変換され、その逆も同様です。

ES6

 for (let i of [1, 2, 3]) { console.log(i) } // 1 // 2 // 3

CoffeeScript

 for i of [1, 2, 3] console.log(i) # 0 # 1 # 2

ES6に切り替える必要がありますか?

私は現在、100%CoffeeScriptを使用してかなり大規模なNode.jsプロジェクトに取り組んでいますが、それでも非常に満足しており、非常に生産的です。 ES6で私が本当に嫉妬しているのは、ゲッターとセッターだけだと思います。

また、今日の実際にES6を使用することはまだ少し苦痛です。 最新のNode.jsバージョンを使用できる場合は、ほぼすべてのES6機能を利用できますが、古いバージョンやブラウザーでは、まだバラ色が少なくなっています。 はい、Babelを使用できますが、もちろんそれはBabelをスタックに統合することを意味します。

とは言っても、来年から2年でES6が大きく成長するのを見ることができ、ES7でさらに大きなものが見られることを望んでいます。

ES6で私が本当に満足しているのは、「昔ながらのJavaScript」が、CoffeeScriptとほぼ同じくらい使いやすく強力なものであるということです。 これはフリーランサーとしての私にとっては素晴らしいことです。以前はJavaScriptプロジェクトでの作業に少し嫌悪感を持っていましたが、ES6ではすべてが少し輝いているように見えます。