18
16

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.

プリミティブ型の暗黙的な型変換

Last updated at Posted at 2015-10-03

はじめに

別の記事を読んでいて、プリミティブ型の暗黙的な型変換について誤解されているようなコードがちょっと気になったので、簡単に解説してみたいと思います。

このコード分かりますか?

まず最初に質問です。以下は正常に動作するコードです。このコードが(3)で最後に出力する値は何でしょうか?また、その理由はなぜでしょうか?
答えはすぐ下にありますが、まずは答えを見ないで考えてください。

//このコードは非strict modeの場合のみ動作します。strict modeの場合は(2)でTypeErrorとなります。

var num = 100; // (1)
num.question = "What is this code ?"; // (2)
console.log(num.question); // (3)

答え

(3)で、console.log(num.question)の出力結果はundefinedとなります。

理由

(2)ではnumは自動的にラッパーオブジェクトに変換され、変換されたオブジェクトのプロパティ(question)に文字列が代入されます。(3)でも同様にnumはラッパーオブジェクトに変換されます。これは(2)とは別のラッパーオブジェクトです。そのため、そのプロパティquestionundefinedとなります。もし,
このコードを意図した(numにプロパティを追加したい)ものにしたければ、(1)では明示的にラッパーオブジェクトを生成する必要があります(こちらに載せてます)。

解説

JavaScriptではプリミティブ型に対するプロパティアクセスが発生した場合、対応するラッパーオブジェクトに暗黙的に型変換が行われます。

  1. (1)では、変数numは数値100を代入しているのでプリミティブ型(number型)となります。
  2. (2)では、numのプロパティquestionにアクセスしていますが、numはプリミティブ型なので、自動的にラッパーオブジェクトであるNumberに型変換されます。
  3. 変換後のオブジェクトのプロパティ(question)に文字列が代入されます。
  4. (3)では、numのプロパティにアクセスしていますが、ここでも自動的にNumberオブジェクトに型変換されます。
  5. 4.で生成されたオブジェクトのプロパティ(question)は存在しないので、undefinedとなります。

ここで、注目して欲しいのは、2.で型変換により生成されたオブジェクトと4.で生成されたオブジェクトは別物だということです。

この暗黙的な型変換をコードで表すと以下のようになります。

var num = 100;

var _numWrapper1 = new Number(num); // ラッパーオブジェクトに変換。
_numWrapper1.question = "What is this code ?";

var _numWrapper2 = new Number(num); // ラッパーオブジェクトに変換。上記のオブジェクトとは別オブジェクト。
console.log(_numWrapper2.question);

ここで、_numWrapper1_numWrapper2は別のオブジェクトであることに注意してください。

応用例

上記のように数値型だけではなく、文字列やブーリアン型などの他のプリミティブ型でも型変換は行われます。

var s = "Hello, world!";
console.log(s.length); // 13
console.log(s.toUpperCase()); // メソッドも呼び出せます。"HELLO, WORLD!"

var n = 10000.123;
console.log(n.toExponential()); // "1.0000123e+4"

var b = true;
console.log(b.toString()); // "true"

このように、プリミティブ型からラッパーオブジェクトへの型変換は自動的に行われるため、以下のように、プリミティブ型をいちいちラッパーオブジェクトに変換する必要はないでしょう。

var s = new String("Hello, world!"); // 自動的に型変換されるので、冗長。
console.log(s.toUpperCase());

ただし、冒頭の質問のように値を永続化したい場合は、以下のように(プリミティブ値にプロパティを追加する是非はおいておいて)ラッパーオブジェクトを使う必要があるでしょう。

var num = new Number(100);
num.question = "What is this code ?";
console.log(num.question); // "What is this code ?";

参考文献

JavaScriptパターン ―優れたアプリケーションのための作法

18
16
2

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
18
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?