为什么`typeof this`返回"对象"?

Phr*_*ogz 8 javascript call ecma262

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"
Run Code Online (Sandbox Code Playgroud)

我在Chrome,Firefox和Safari中看到相同的结果,所以我认为它符合规范,但是......为什么?这个规范中的定义是什么?为什么不用于功能呢?

jba*_*all 11

根据ECMA-262 ECMAScript语言规范第3版(见脚注)中的定义,它基于规范(第15.3.4.4节):

var result = fun.call(thisArg[, arg1[, arg2[, ...]]]);  
Run Code Online (Sandbox Code Playgroud)

参数

thisArg

确定这个内部乐趣的价值.如果thisArg为null或未定义,则这将是全局对象.否则,这将等于Object(thisArg)(如果thisArg已经是对象,则为thisArg,如果thisArg是相应类型的原始值,则为String,Boolean或Number).因此,当函数执行时,这个=="对象"的类型总是正确的.

特别注意最后一行.

关键的东西是JS元(string,number,boolean,null,undefined)是不可改变的,所以功能无法连接到他们.因此,该call函数将原语包装在一起,Object以便可以附加该函数.

例如:

不起作用:

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

作品:

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

(脚注) - 正如patrick dw在评论中指出的那样,在严格模式下,这将在ECMA-262 ECMAScript语言规范第5版中发生变化:

从第15.3.4.4节:

注意thisArg值未经修改即作为此值传递.这是对第3版的更改,其中未定义或null thisArg将替换为全局对象,ToObject将应用于所有其他值,并且结果将作为此值传递.

  • 请注意,这会从ECMAScript 5开始更改.从第15.3.4.4节开始:*注意thisArg值未经修改即作为此值传递.这是对版本3的更改,其中未定义或null thisArg替换为全局对象,ToObject应用于所有其他值,并将结果作为此值传递.* (3认同)