質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

3回答

2342閲覧

【JavaScript】プリミティブ型である文字列値とStringオブジェクトについて

takenyaan

総合スコア119

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

3クリップ

投稿2015/05/11 12:58

掲題の件について質問です。

プリミティブ型である文字列値とStringオブジェクトについてですが、
値がどのように格納されているのかご教示下さい。

プリミティブ型

lang

1var str = "hoge"; 2alert(str); // hoge

Stringオブジェクトの場合

lang

1var str = new String("hoge"); 2alert(str); //hoge

プリミティブ型については直観的に理解できるのですが、
オブジェクト型のStringについてコンストラクタに指定した"hoge"という値はstrオブジェクトの何に格納されるのでしょうか。
オブジェクトはプロパティとメソッドから成り立つと認識しているため、"hoge"という値にアクセスするためには、「str.プロパティ名」とする必要があるように思えるのですが。

とんちんかんな質問で申し訳ございません。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

どのようにPrimitiveValueが格納されているか回答できなくて申し訳ないのですが、
Tak1waさんの仰るとおり、Stringオブジェクトには必要に応じてtoString()やvalueOf()が行われているようですね。

lang

1var str = new String("hoge"); 2 3// StringオブジェクトであるstrのtoString, valueOfをオーバーライド 4str.toString = function () { 5 console.log(".toString()"); 6 return String.prototype.toString.call(this); 7}; 8str.valueOf = function () { 9 console.log(".valueOf()"); 10 return String.prototype.valueOf.call(this); 11}; 12 13// toString()が呼ばれる 14alert(str); // "hoge" 15alert(str.toString()); // "hoge" 16alert(new String(str)); // "hoge" 17alert(String(str)); // "hoge" 18alert(new Object(str)); // "hoge" 19alert(Object(str)); // "hoge" 20 21// valueOf()が呼ばれる 22alert("" + str); // "hoge" 23alert("hoge" == str); // true 24alert("hoge" === str); // false 25alert(+str); // NaN 26alert(1 + str); // "1hoge" 27alert(0 == str); // false 28alert(0 < str); // false 29alert(0 <= str); // false 30alert(true == str); //false 31alert(new Number(str)); // NaN 32alert(Number(str)); // NaN 33alert(new Boolean(str)); // true 34alert(Boolean(str)); // true

【おまけ】 実際こんなトリッキーなコードを使うことは無いでしょうが、こんなことも出来るようですね。

lang

1 2var str = new String("10"); 3 4// 当たり前 5alert(str); // 10 6alert(+str); // 10 7 8str.toString = function () { 9 console.log(".toString()"); 10 return "1"; 11}; 12str.valueOf = function () { 13 console.log(".valueOf()"); 14 return -1; 15}; 16 17// !!!? 18alert(str); // 1 19alert(+str); // -1 20 21alert(String.prototype.toString.call(str)); // 10 22alert(String.prototype.valueOf.call(str)); // 10 23

なかなか奥が深いです

投稿2015/05/11 22:15

MAGP

総合スコア153

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

okayu3

2015/05/12 02:17

すばらしいですね。 たしかに +str のときにvalueOf るのは 仕様通り! ただし、 var so = new String("abc"); "abc" === so.valueOf(); //true "abc" === +so; // false となり、 valueOf そのものではないようですね。 var so = new String("123"); 123 === +so; // true となり、"+" の場合に valueOf したあと evalしていることが伺えます。 わたしが 普段 valueOf を使うのは、 "===" で同一文字列かを調べるときで ex. sObj0.valueOf() === sObj1.valueOf() だけど、これは どうも コストが高い気がしてなんとなく後ろめたかったんですが、 堂々やってもいいかもしれないと思いました。
MAGP

2015/05/12 08:54

コメント有難うございます。 ご指摘の通り、valueOfの結果そのものにはならなかったですね。 > "+" の場合に valueOf したあと evalしていることが伺えます。 「+」演算子を使うとNumberへ変換されるため、恐らくNumber(so.valueOf())のような動作をしているのではないでしょうか(間違っていたらすみません…)
guest

0

こんにちは。

JavaScriptには疎いですが…。
少し調べてみた限りではtakenyaanさんの考察で合っているような気がします。

オブジェクトはプロパティとメソッドから成り立つと認識しているため、"hoge"という値にアクセスするためには、「str.プロパティ名」とする必要があるように思えるのですが。

以下によると、文字列を得るためには、valueOfまたはtoStringを呼び出す必要があります。
http://hakuhin.jp/js/string.html

ではなぜ、alert(str); で「hoge」が得られるかと言うと、これは以下を信じるならば、alert関数が自動でtoStringしているだけなのではないでしょうか。
http://www.ajaxtower.jp/js/object_class/index3.html

なので、プリミティブと同様に扱われているように見えるところは、参照型の場合は自動的にtoStringまたはvalueOfされているのではないか、と予想します。(ここまで書いてみたものの自信がイマイチ。出所が確かな情報が欲しいですね。JavaScriptの場合はどこのサイトがよろしいのか…。)

投稿2015/05/11 16:16

Tak1wa

総合スコア4791

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

うーんと、property と value の形で外から見えるようにできる、というだけのことであって、
必ずしも Object classを継承したからといって、内部構造がそのようになっているとは
限りません。(仕様が決まっているだけで。)

とはいえ、とりあえず for in でプロパティを見たくなるのは人情ですね。
というわけで、

lang

1var s = new String('abcde'); 2for (var a in s) {window.console.log(a + ":" + s[a]);}

とすると、

lang

10:a 21:b 32:c 43:d 54:e

と返ります。文字 の配列のような見え方をしますね。では 文字列 (not object)ではどうなのでしょうか。

lang

1var s0 = String('fghij'); //newがないことに注意。 2for(var a in s0) {window.console.log(a + ":" + s0[a]);}

とすると

lang

10:f 21:g 32:h 43:i 54:j

と、同じようなものが帰ってきます。
というわけで、このレベルでの違いは for in では見えません。
#ただし、string Object では、length, "proto" といった (見えてこない)プロパティもあります。

String Objectと 文字列との違いは、
0. "===" による比較で結果が違うということ、
0. typeOf による結果が違う (文字列は "string", String Objectは "object") こと、
0. eval の結果が異なる (eval(String('2+2')) と eval(new String('2+2')) が違う) こと
ぐらいが目に見える 違いでしょうか。

わたしは処理系の実装までは調査しませんでしたので、この回答ではご不満かもしれません。
他の回答者の答えもご参考にしてくださいね。

投稿2015/05/11 16:07

okayu3

総合スコア200

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問