2010-12-08 105 views
8
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中看到了相同的結果,所以我假設它是每the spec,但是......爲什麼?規範中的這個定義在哪裏?爲什麼不爲功能?爲什麼`typeof this`返回「object」?

+0

哇,從來不知道。現在我想知道爲什麼這也是! – Matt 2010-12-08 18:03:05

回答

11

如在ECMA-262的ECMAScript語言規範第三版(見腳註)中所定義,它是基於the spec(第15.3.4.4):

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

參數

thisArg

確定這個值在 的樂趣。如果thisArg爲空或未定義,則這將是全局對象。 否則,這將等於 對象(thisArg)(其是thisArg如果 thisArg已經是一個對象,或 字符串,布爾值,或者如果數目thisArg 是 相應類型的原始值)。因此,當該函數執行時,它總是屬於這個== 「object」。

特別注意最後一行。

關鍵的東西是JS元(stringnumberbooleannullundefined)是不可改變的,所以功能無法連接到他們。因此,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(); 

(腳註) - 作爲patrick dw在評論中指出,這將在ECMA-262 ECMAScript Language Specification 5th edition改變時嚴格模式:

從第15.3.4.4:

注的 thisArg值,而不修改 作爲此值傳遞。這 是從版本3,其中一個 未定義或null thisArg替換 與全局對象和ToObject是 應用於所有其他值和 結果作爲此值傳遞。

+3

請注意,從ECMAScript 5開始更改。從第15.3.4.4節開始:*注意\t thisArg值未經修改就作爲此值傳遞。這是從版本3開始的一個變化,其中未定義的或null的thisArg被替換爲全局對象,並且ToObject被應用於所有其他值,並且結果作爲該值傳遞。* – user113716 2010-12-08 18:15:23

相關問題