为什么 JavaScript 的 typeof 总是返回 "object"?

28

如果它总是返回object作为类型,那么它有什么用处?

总是用于元素列表


14
它很有用,因为它不会做那件事。 - Kirk Woll
一些客户端从“getElementsByTagName”等方法返回的nodeList的typeof = 'function'。我提到这点是因为最近在windows上使用Safari时遇到了问题。 - kennebec
console.log(typeof "foo"); // 字符串 console.log(typeof String("foo")); // 字符串 console.log(typeof new String("foo")); // 对象。请注意使用了 new - Jowen
8个回答

23

JS的typeof并不总是返回'object',但对于一些人不认为是对象的东西,比如数组和空值,在这种情况下也会返回object。

对于数组来说,这是正确的,因为JS认为数组就是对象;它们是同样的东西。数组只是另一个类,你可以使用Array类型实例化对象,但它们仍然被视为对象。

此页面列出了JS中的类型及每种类型的typeof响应。该页面还提供了一些JS代码,用于覆盖typeof函数,并返回更有用的信息。如果你担心它不太有用,你可以自己实现类似的内容。


链接已失效 :/ - Augustin Laville

11

它并不总是返回"object":

alert(typeof "hello");

话虽如此,一种(可能)更有用的检查对象的技巧是使用Object.prototype.toString.call()并查看结果:

var t = Object.prototype.toString.call(itIsAMystery);

这将会给你一个字符串,像是[object Foo],其中"Foo"是有趣的部分,对于"native"类型(如Date或String),你会得到它们的构造函数名称。

1
...其中"Foo"是[[Class]]内部属性的值,它代表了原生对象的规范定义的分类(并不是真正的类型!),对于宿主对象来说,它基本上可以是任何东西... - Christian C. Salvadó
请注意,typeof运算符对于函数的this作用域始终返回“object”(除非该作用域恰好是一个函数)。请参阅"Why does typeof this return “object”?" - Phrogz

5

并非所有的typeof返回对象。

对象,数组正则表达式返回object类型。

函数是一个对象(引用类型),但返回function类型。这是语言中的一种不一致性。

另外需要注意的是,undefined返回undefined,而null返回object,这是JS中的一个错误。

NaN(不是数字)返回number类型。

最好你要记住所有这些,并了解这些奇怪的行为。

以下是所有值的类型供参考:

typeof "Tamal" ---> string
typeof 100 ---> number
typeof true ---> boolean
typeof false ---> boolean
typeof undefined ---> undefined
typeof function() {} ---> function
typeof Symbol() ---> symbol
typeof {name: "Tamal"} ---> object
typeof [1, 2, 3] ---> object
typeof /^/ ---> object
typeof NaN ---> number
typeof null ---> object (bug)

很好,你已经包含了在ECMA 2015(又称ECMA 6)中引入的Symbol数据类型。 - RBT

5

根据我的经验,typeof 的主要问题在于区分数组、对象和 null(它们都返回 "object")。

为了解决这个问题,我首先检查 typeof,然后检查 null 情况或者 "object" 的构造函数,像这样:

for (o in obj) {
    if (obj.hasOwnProperty(o)) {
        switch (typeof obj[o]) {
            case "object":
                if (obj[o] === null) {
                    //do somethign with null
                } else {
                    if (obj[o].constructor.name === "Array") {
                        //do something with an Array
                    } else {
                        //do something with an Object
                    }
                }
                break;
            case "function":
                //do something with a function
                break;
            default:
                //do something with strings, booleans, numbers
                break;
        }
    }
}

3
为了与其他内容一起添加,typeof返回对象和原始类型。在JavaScript中有5种原始类型:undefined、null、boolean、string和number。所有其他的都是对象。当typeof应用于除Function以外的任何对象类型时,它只返回“object”。当应用于一个函数时,它返回一个函数对象。
所以,例如:
  • typeof true; //返回原始类型"boolean"
  • typeof 123; //返回原始类型"number"
  • typeof null //返回"object",这是一个错误,但到目前为止在另一个ECMAScript版本中没有修复,只是谈论如何修复。
  • typeof object //返回"object",这是有意义的
进一步解释Pointy的答案,在ECMAScript 5中每个JavaScript对象都有一个名为[[Class]]的内部属性。为了显示对象的实际值,可以使用Object.prototype.toString引用[[Class]]属性。为避免一些专用的内置对象覆盖toString,您可以使用调用的内部方法来显示实际对象类型。
因此,与其从toString中获取通用对象,
var dateObject = Object.prototype.toString(new Date);
document.write(dateObject);//[object Object]

您可以使用Call获取实际的对象类型:
var dateObject = Object.prototype.toString.call(new Date);
document.write(dateObject);//[object Date]

1

使用typeof操作符时需要小心。对于null,返回"object",对于NaN,返回"number",对于Infinity,返回"number",对于"new Number(1)"和数组,返回"object"。

当检查变量的存在性(typeof variable !== "undefined")时,有时需要首先检查(variable == null),因为typeof对于分配给null的变量返回"object"。

显而易见的是,在检查typeof时不要调用函数,因为函数的返回类型将被报告,而不是"function"。


这对我的情况很有帮助,因为我正在迭代数字、字符串、null 和对象。我能够将对象与 null 分离以进行转换。 - Joshua Fricke

1

typeof 是一个操作符,接受一个操作数,返回一个字符串,指示操作数是原始值、函数、对象还是未声明

需要注意的是,typeof 不会返回与用于构造对象的类或构造函数名称相对应的字符串,因此你的问题。

typeof 对于 七种 原始 JavaScript 类型返回以下内容:

  1. Undefined: 'undefined'
  2. Null: 'object'
  3. Boolean: 'boolean'
  4. Number: 'number'
  5. BigInt: 'bigint'
  6. Symbol: 'symbol'
  7. String: 'string'
(...对于建议的BigDecimal原始类型,我认为它将返回'bigdecimal'。) typeof 对对象/对象类别返回以下内容:
  1. document.all'undefined'
  2. 函数: 'function'
  3. 所有其他普通对象: 'object'
最后,typeof 对未声明的标识符返回'undefined'
注释

typeof 返回 'object' 用于 null尽管 null 是 Null 类型, 这是因为早期需要与 Java 轻松互操作的要求,而在 Java 中,null 是空的引用类型。 null 位于每个原型链的顶部,并且可以被视为在对象类型原语集合中。

typeof 对于函数返回 'function',而不是 'object'以便轻松识别函数(即可调用对象)而无需在语言内部公开单独的 isFunctionisCallable 函数。

typeof 是 JavaScript 中仅有的一种机制,可以检测未声明的标识符(参见规范中第2步a),而不会抛出错误。这在尝试动态检测主机环境(例如 Node.js 或 Web 浏览器)时非常有用,因为被测试的标识符可能存在也可能不存在。

如果在暂时性死区内使用 typeof 来检测标识符,则会抛出运行时错误(即正常行为)。

document.all 是 Web 平台中的一个对象(即不是语言的一部分),typeof 返回 undefined。为了保持与早期 Web 浏览器的兼容性,语言规范对此进行了特殊处理。

new Number(1)new Boolean(true) 这样的原始包装对象被视为对象,而不是原始类型。因此,例如,typeof new Number(1) 返回 'object'。请注意,typeof Number(1) 返回 'number',因为在没有 new 操作符的情况下,这些构造函数返回一个原始类型的实例。

"typeof" 是一个运算符,而不是一个函数。尽管它可以使用类似函数调用的语法(例如 typeof(foo)),但表达式的右侧是一个普通的一元表达式:括号并不表示函数调用,而是一个表达式。

1
令人难以置信的答案 - user3064538

-1
你必须理解 JavaScript 中的类型系统是动态的,有一些“原始”类型可供构建。通过将所有复杂对象视为类型“object”,这使您可以进行鸭子类型并调用方法,而不必知道传递的对象类型,假设该类型已实现函数调用。在动态编程语言中,一切都是“对象”。

鸭子类型的语言并不总是省略类型 - 例如,Python 是一种鸭子类型的语言,并且具有一个有用的 type() 函数,可以告诉你对象的类型。 - mikemaccana
你可能可以将任何类型传递到任何地方,但这并不意味着除了对象之外就没有其他类型了。 - byxor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接