2010-12-08 81 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

相关问题