Почему `typeof this` возвращает« объект »? - PullRequest
8 голосов
/ 08 декабря 2010
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, поэтому я предполагаю, что это соответствует спецификации , но ... почему? И где в спецификации это определено? А почему не для функций?

1 Ответ

11 голосов
/ 08 декабря 2010

Как определено в ECMA-262 ECMAScript Language Specification 3-е издание (см. Сноску), он основан на спецификации (Раздел 15.3.4.4):

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

Параметры

thisArg

Определяет значение этого внутри веселья.Если thisArg имеет значение null или не определено, это будет глобальный объект.В противном случае это будет равно Object (thisArg) (который является thisArg, если thisArg уже является объектом, или String, Boolean или Number, если thisArg является примитивным значением соответствующего типа).Поэтому всегда верно, что typeof this == "object" при выполнении функции.

Обратите внимание, в частности, на последнюю строку.

Важно то, что 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();

Работы:

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 Спецификация языка 5-е издание в строгомmode:

Из раздела 15.3.4.4:

ПРИМЕЧАНИЕ Значение thisArg передается без изменения как значение this.Это изменение по сравнению с выпуском 3, где неопределенный или нулевой thisArg заменяется глобальным объектом, а ToObject применяется ко всем другим значениям, и этот результат передается как значение this.

...