プリミティブ文字列値とString
オブジェクトには違いがあります。
'foo' // primitive
new String('foo') // object
文字列プリミティブで String メンバー関数を呼び出すと、関数内の値になる String オブジェクトにラップされthis
ます。(この動作については、以下で詳しく説明します。)
したがって、 inremoveExtension
はオブジェクトですthis
。String
一方、組み込み関数this.substr
はプリミティブを返します。それが定義されているだけです。this
したがって、 ( String
objectthis.substr
) を返すときと(string Primitive )の結果を返すときは、異なることがわかります。オブジェクトの文字列プリミティブ バージョンを返したい場合はthis
、単にthis.toString
.
Number
sなどのどのプリミティブでも同じラッピング動作が見られます。
Number.prototype.returnThis = function() { return this; }
typeof 2; // 'number'
typeof (2).returnThis() // 'object' (a Number object, specifically)
なぜこれが起こるのか本当に知りたい場合は、ECMAScript 仕様にあります。
10.4.3 機能コードの入力
関数オブジェクト F に含まれる関数コードの実行コンテキストに制御が入ると、次の手順が実行されます。
- 機能コードが厳格なコードの場合は、 を に設定
ThisBinding
しthisArg
ます。
- それ以外の場合、thisArg が null または未定義の場合は
ThisBinding
、グローバル オブジェクトに設定します。
Type(thisArg)
が Object でない場合は、 を に設定ThisBinding
しToObject(thisArg)
ます。
- ....
ポイント #3 が重要です。プリミティブ値 (つまり、非オブジェクト) で関数を呼び出すと、対応するオブジェクト形式に変換されます。