ためしてみるとすぐわかる違い。前提として、JavaScript では「全てオブジェクトというわけではない」ことを覚えておく必要があります (Ruby との違い)。
uneval("foo"); //=> "\"foo\"" "foo".toSource(); //=> "(new String(\"foo\"))"
なぜこのような違いが生まれるか、というと 11.2.1 プロパティアクセス演算子 (Property Accessors) にある
生成規則 MemberExpression : MemberExpression [ Expression ] は次のように評価される:
- MemberExpression を評価。
- GetValue(Result(1)) を呼出す。
- Expression を評価。
- GetValue(Result(3)) を呼出す。
- ToObject(Result(2)) を呼出す。
- ToString(Result(4)) を呼出す。
- 基準オブジェクトが Result(5) でプロパティ名が Result(6) である Reference 型の値を返す。
の ToObject(Result(2)) がキモです。
JavaScript において
"foobar" typeof "foobar" //=> "string"
は、typeof すればわかるように Primitive な String 型であって、String オブジェクトのインスタンス (Object 型) ではありません。プロパティアクセス演算子が使われると、そのつど String オブジェクトへ変換されます。
これは以下のようにすればすぐわかります。
String.prototype.returnThis = function () { return this }; typeof "foobar".returnThis(); //=> "object" "foobar".returnThis() === "foobar".returnThis(); //=> false
レシーバは "foobar" にみえますが、上の結果と違っています。これはプロパティアクセス演算子の作用で ToObject された結果が this として渡されているからです。(ToObject は処理系の内部関数なので JS から直接はよべません)
ここでなんとなく気付くと思いますが、this は Object 型以外の型には絶対になりません。this を明示して渡せる call や apply でさえ this に対しては ToObject で変換がかかります。
そうなると、Object に変換されるまえの、Primitive な値がほしいときに (そんなケースあんまりありませんが)、ちょっと困るので、そういうときに valueOf() をつかいます。valueOf() って説明だけ読みとなにがしたいのがさっぱりわかりませんが、こいつを使ってやることで、本来のレシーバ (のようにみえる値) をとることができます。
"foobar".valueOf() //=> "foobar"
この valueOf() はどんなオブジェクトにも存在するので安心して本来のレシーバを取得することができます。(Primitive 値のラッパオブジェクトでは Primitive 値になるし、そうでなければ単に this をかえすだけです)
valueOf には Date オブジェクトみたいに this 以外をかえすのもあります。