84
56

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JavaScript の Number() は副作用がある可能性がある

Posted at

たまたまTwitterを見てたら以下のようなツイートを見かけました。

image

つまり、 isNumber っていう関数を作るなら一旦Numberでキャストした値と同一かどうかを比較すれば良いと。おそらく NaN を省いた number 型を true にしたいのかなという感じがする (NaN === NaN は必ず false)。

ただこれには問題があるらしく、 V8 のOptimizerリーダーである bmeurer から下記のようなレスが付いてました。

image

Number() では意図しない副作用があるかもしれない」という意味のレス。最初意味がわからなくて、「おや?」と思ったんですけど、その後で補足が。

image

ToPrimitive関数が呼ばれてしまい、意図しないJSの動きをするかも。」とのこと。

つまり、

var a = {
  x: 1,
  [Symbol.toPrimitive]: function() {
    this.x++;
    return this.x;
  }
};

みたいなオブジェクトがあったら、 Number 関数が呼ばれる度に a.x がインクリメントされてしまう。

$ node > Number(a)
<- 2
$ node > Number(a)
<- 3
$ node > Number(a)
<- 4

これだけじゃなくて、 +a でも呼ばれるはず

$ node > +a
<- 5
$ node > +a
<- 6
$ node > +a
<- 7

上記の条件(NumberだけどNaNをfalseにしつつ、副作用を伴わない)を満たすisNumber関数を作るなら、横着せずにちゃんと typeof a === 'number'Number.isNaN でチェックするのがいいんだろう。

いやでも待てよ、それだとすると、副作用を伴わずにNumber型にキャストするっていう手段はないのか・・・?どうしよう、って思ったら Dr. Axel 先生からの締め。

image

parseNumber っていう関数あるといいのかもねーっていう。こうしてJSにまた1つ関数が追加されるのかしら。

84
56
1

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
84
56

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?