Когда, если вообще, Javascript "typeof" возвращает неправильный тип?

Я пытаюсь проделать свой путь через код другого, и я нахожу некоторые причудливые вещи. Я нашел следующий код в части программы:

if(typeof func == "function" || (typeof func == "object" && typeof func.document == "undefined"))
{
 func();
}

Это не имело для меня никакого смысла, поскольку я не был уверен, когда такое событие может случиться? Может ли typeof возвращать неправильный тип? Или возможно, что объект, не являющийся функцией, может быть вызван?

Код - беспорядок, поэтому я не могу найти пример того, где эта конкретная проверка может быть успешной. Я должен отметить, что код может быть старше 10 лет. Утверждение, которое я получил, было то, что это требовалось, потому что иногда, когда код был первоначально написан, typeof не возвращал функцию как тип.

Кроме того, эта проверка требовалась, потому что иногда func передавался объекту window (?), поэтому необходимо было убедиться, что он также не является объектом окна.

2 ответа

Помните: typeof для литералов.

typeof undefined === "undefined"
typeof 5 === "number"
typeof true === "boolean"
typeof "" === "string"
typeof {} === "object"
typeof [] === "object"
typeof function { } === "function"
// null is a weird exception:
typeof null === "object"

instanceof различает, когда что-то есть "функции" (обратите внимание, что где typeof проверяет строку "object" instanceof проверяет непосредственно на функции Object:

{} instanceof Object
function {} instanceof Object
function {} instanceof Function
[] instanceof Object
[] instanceof Array

Как вы видите, typeof говорит === "function" и !== "object": это может ввести в заблуждение, потому что функция также является объектом. Это когда instanceof вступает в игру.

Теперь, когда вы пишете конструктор, построенный объект также является экземпляром вашей функции:

// the constructor
function Example { }
// the object
var ex = new Example();
typeof Example === "function"
typeof ex === "object"
ex instanceof Object
ex instanceof Example

Используя прототип, вы также можете расширить цепочку, где typeof всегда говорит объект:

function DerivedExample { }
DerivedExample.prototype = new Example();
// DerivedExample.prototype.constructor = DerivedExample;
var ex1 = new DerivedExample();
typeof DerivedExample === "function"
typeof ex1 === "object"
ex1 instanceof Object
ex1 instanceof Example
ex1 instanceof DerivedExample

Итак, все о javaScript typeof, а также instanceof. Надеюсь, он разъяснит, что происходит.

Что-то также полезно знать (это не рекомендуется использовать в производственном коде, но я также видел его в источнике CoffeeScript):

typeof new Number(5) === "object"
new Number(5) instanceof Object
new Number(5) instanceof Number
typeof new Boolean("true") === "object"
new Boolean("true") instanceof Object
new Boolean("true") instanceof Boolean
typeof new String("") === "object"
new String("") instanceof Object
new String("") instanceof String

О функциях и объекте window:

Каждая отдельная функция будет вызываться в контексте окна. (За исключением), когда вы "use strict" "директива", автономная функция будет вызвана с контекстом undefined.

function world() {
 // non-strict: this === window
 // use-strict: this === undefined
}
world();

Теперь, когда вы пишете функцию как член объекта, контекст функции является объектом:

var hello = {
 world: function () {
 // this === hello
 }
};
hello.world();

Это также верно для прототипов функций, которые вызывается в контексте вновь созданного объекта:

function Hello() { }
Hello.prototype.world = function () {
 // this instanceof Hello
 // this will be === ex
};
var ex = new Hello();
ex.world();

И по крайней мере, вы можете изменить контекст любой функции с помощью call и apply:

var ex = { };
function Example() {
 // (1) non-strict: this === window
 // (1) use-strict: this === undefined
 // (2) this === ex
}
Example(); // (1)
Example.call(ex); // (2)
Example.apply(ex); // (2)


Рассмотрим этот пример

var a = [];
typeof a; // object
Object.prototype.toString.call(a); // [object Array]
var b = {};
typeof b; // object
Object.prototype.toString.call(b); // [object Object]

Итак, да, typeof может быть довольно запутанным иногда

licensed under cc by-sa 3.0 with attribution.