0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

手癖でコードを書いてしばらく悩んだ話

Posted at

問題

以下のようなコードを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 に文章で聞いてみると意図した通りの結果にはならないという応答が返ってきたので、こういう記号が入った式の質問をするときには便利に使えると思う。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?