はじめに
最近アサイン中のプロジェクトでのeslintが厳格化したので、その解析エラーの対応をしていた時のメモ
ハマったとこ①
エラーを吐くソースコードはコレ。
ちなみにVueで書いてます。
data() {
return {
amountErrors: []
};
},
created() {
for (let formName in this.errors) {
let messageOrder = formName.split('.')[1];
if (formName.match(/amount/)) {
this.amountErrors[messageOrder] = this.errors[formName][0];
}
});
},
実際のエラーはコレ。
for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array. (no-restricted-syntax
Deeplによる日本語訳は
for..inループはプロトタイプチェーン全体を繰り返し処理しますが、これは事実上望んだものではありません。Object.{キー,値,エントリ}を使用し、結果の配列に対して反復処理を行います(無制限構文)。
とのこと。
ちょっと理由まで把握しきれませんでしたが、eslintとしては「事実上望んだものではありません」とのことなので、エラーが出るんだな、と把握
ググってみると…
とはいえ、先ほどのエラー文で検索した結果の記事の一つに
「私はforEachに変更して解決しました。」
とあったので、参考にさせてもらった
「なんでforEach?」と思ったが
- 反復処理ができる(これは知っている。PHPとかとイメージ合う)
- コールバック関数で引数を持たせることができる(?!)
ことが分かりました。
後者の「引数を持たせることができる」ってのが前述のeslintのエラー文の「Object.{キー,値,エントリ}を使用し」に該当するんだな、と推測
※追記
ここについては @htsign さんのコメントが参考になるので、合わせてご確認くださいませ。
対応
なので、さっきのコードを以下のように変更
Object.keys(this.errors).forEach(function makeErrors(formName) {
let messageOrder = formName.split('.')[1];
if (formName.match(/amount/)) {
this.amountErrors[messageOrder] = this.errors[formName][0];
}
});
for...in構文をforEachに変更しただけ
これでeslintは通るようになりました。よかったよかった。
その他参考
ハマったところ②
さらにハマりました。笑
原因は元々for分内で使っていたthis
forEachに変更したコードをブラウザで動かすと
Uncaught TypeError: Cannot read properties of undefined (reading 'amountErrors')
と言うコンソールエラーが表示されてコードが動きませんでした。
dataプロパティであるamountErrorsを参照しているthisがundefinedになっているらしい。
対応
どうもstrict モードだと関数コンテキスト内ではグローバルコンテキストが参照できずundefinedが返る。
なのでforEach内でなにもしなければthis
は undefined
になる。
じゃあどうするのかと言うとforEachは第二引数に値を渡すと、渡された値がforEach内でも使える、とのこと。(先ほどのforEachの説明のところにしれっと書かれている)
なので、こうしてみた。
Object.keys(this.errors).forEach(function makeErrors(formName) {
let messageOrder = formName.split('.')[1];
if (formName.match(/amount/)) {
this.amountErrors[messageOrder] = this.errors[formName][0];
}
}, this);
これで今まで通りカードが動くようになり、マージリクエストを出すことができました〜
おわりに
普段PHP使ってる自分からしたらJSの forEachはPHPと同じように使えない点で、すごくクセがある気がしてなるべく避けていたんですが今回いい機会でした。笑
特にforEachはreturn;
やbreak;
による中断処理ができない点で詰まったトラウマがあって…
第一引数のクロージャーの中にもいろいろ引数を渡すことができて、できること多いんだなぁと知れたので、少しづつ慣れていこうかと思います
お読みいただきありがとうございました。