問題
以下のようなコードをJavaScriptで書いた。
class ContentList {
constructor(contents) {
this.contents = contents;
}
getContent(n) {
if (0 <= n < this.contents.length) {
return this.contents[n];
}
return null;
}
}
なんとなく違和感を感じつつも、実際に使ってみると以下のようになった。
const list = new ContentList([...]); // contents を初期化
list.getContent(0); // この結果が null となる
当然、想定した結果ではなく最初のコンテンツが欲しかった。
原因
なぜ問題が起こったのか。 それは if の条件式 (0 <= n < this.contents.length)
の部分である。
この a < b < c
のような条件の記載は Python ではよく用いられる。
JavaScript でも構文チェッカーがエラーを出さず構文としては正常なのだが、Python とは異なる結果を返す。 JavaScript では
- 最初に a < b を評価して bool 値を得る
- 次に (a < b) < c を評価するが、この時真偽値は
0 = false
,1 = true
として整数にキャストされて評価される
という順で評価が行われる。
今回は n
が 0 , contents
の長さが1だったので、(0 <= n < this.contents.length)
= ((0 <= 0) < 1)
= (1 < 1)
= false
という形で評価され、想定通りの結果が得られなかった。
このような問題を起こさないようにするには、(0 <= n && n < this.contents.length)
とちゃんと &&
で個別の条件を記載すればよい。
教訓
今回は構文エラーにならなかったので JavaScript でも a < b < c
という範囲計算ができると裏どりをせずに信じ込んでしまったのが原因。 違和感がある場合、ちゃんと使えるかどうかを裏どりをしよう。
同様の事例を Google で検索しようとしてもどのようなキーワードで調べてよいかがわからなかったが、ChatGPT に文章で聞いてみると意図した通りの結果にはならないという応答が返ってきたので、こういう記号が入った式の質問をするときには便利に使えると思う。