9
var f = function(o){ return this+":"+o+"::"+(typeof this)+":"+(typeof o) };
f.call( "2", "2" );
// "2:2::object:string"

var f = function(o){ return this+":"+(typeof this)+":"+(typeof o); };
var x = [1,/foo/,"bar",function(){},true,[],{}];
for (var i=0;i<x.length;++i) console.log(f.call(x[i],x[i]));
// "1:object:number"
// "/foo/:object:object"
// "bar:object:string"
// "function () {\n}:function:function"
// "true:object:boolean"
// ":object:object"
// "[object Object]:object:object"

Chrome、Firefox、Safari で同じ結果が表示されるので、仕様どおりだと思いますが、なぜですか? そして、これは仕様のどこで定義されていますか? そして、関数ではないのはなぜですか?

4

1 に答える 1

11

ECMA-262 ECMAScript 言語仕様第 3 版 (脚注を参照) で定義されているように、仕様(セクション 15.3.4.4)に基づいています。

var result = fun.call(thisArg[, arg1[, arg2[, ...]]]);  

パラメーター

thisArg

この inside fun の値を決定します。thisArg が null または未定義の場合、これはグローバル オブジェクトになります。それ以外の場合、これは Object(thisArg) (thisArg が既にオブジェクトである場合は thisArg、または thisArg が対応する型のプリミティブ値である場合は String、Boolean、または Number) と等しくなります。したがって、関数が実行されるとき、typeof this == "object" は常に true です。

特に最後の行に注意してください。

重要なことは、js プリミティブ ( stringnumberboolean、 ) は不変nullundefinedあるため、関数をそれらにアタッチできないことです。したがって、call関数はプリミティブを でラップしObjectて、関数をアタッチできるようにします。

例えば:

動作しません:

var test = "string";
//the next 2 lines are invalid, as `test` is a primitive 
test.someFun = function () { alert(this); }; 
test.someFun();

作品:

var test = "string";
//wrap test up to give it a mutable wrapper
var temp = Object(test);
temp.someFun = function () { alert(this); };
temp.someFun();

(脚注) -パトリック dwがコメントで指摘したように、厳密モードの場合、これはECMA-262 ECMAScript 言語仕様第 5 版で変更されます。

セクション15.3.4.4から:

注意 thisArg 値は、変更せずに this 値として渡されます。これは、未定義または null の thisArg がグローバル オブジェクトに置き換えられ、ToObject が他のすべての値に適用され、その結果が this 値として渡される第 3 版からの変更です。

于 2010-12-08T17:58:20.617 に答える