You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何JavaScript中NaN.typeof()与Object.prototype.typeof(NaN)结果不同?

问题:调用NaN.typeof()与Object.prototype.typeof(NaN)结果不一致的原因

我编写了一段代码,旨在便捷判断变量类型,弥补原生typeof的不足(例如数组会被识别为'object')。大部分场景下表现符合预期:比如'this is a string'.typeof()与Object.prototype.typeof('this is a string')均返回'String';但调用NaN.typeof()时返回'Number',而Object.prototype.typeof(NaN)却能按预期返回'NaN',希望理解这两种调用结果不同的原因。

相关代码如下:

if (!Object.prototype.hasOwnProperty('stringify')) {
    Object.defineProperties(Object.prototype, {
        stringify: {
            value: function () { 
                if (arguments.length >= 2) return JSON.stringify(this, ...arguments); //this means replacer is used
                return JSON.stringify(this, null, ...arguments) } //when replacer ( function, array) is skipped.
        },
        getType: { value: function(target) {
                if (arguments.length === 0) target = this; //assuming no error, variable.typeof() will yield the target. To avoid error use Object.prototype.typeof(target);
                if (typeof target === 'number' && Number.isNaN(target)) return 'NaN';//NaN.typeof() will return "number" even if it's not a number
                if (typeof target !== 'object') return typeof target; //when typeof returns a primitive (Function, String, Number, BigInt, Symbol, Boolean, undefined); 
                const return_value = Object.prototype.toString.call(target);
                // we can also use regex to do this...
                const type = return_value.substring(
                        return_value.indexOf(" ") + 1, 
                        return_value.indexOf("]"));
                return type.toLowerCase();
            }
        },
        typeof: {value: function(target) { //this should be same as getType() above. weird that NaN.typeof() still  yields 'Number' but Object.prototype.typeof(NaN) yields 'NaN'
            if (arguments.length === 0) target = this; //in case target is of 'null' value;
            return target === undefined ? 'undefined' : target === null ? 'null' : Object.is(NaN, target)? 'NaN' : target.constructor.name;
        }},
        isTypeof: {value: function(type, val) {
            return ([undefined, null].includes(val) && val === type) || Object.is(NaN, val) || val.constructor.name === type;
        }},
        is: {value: function() {
            if (arguments.length === 1) {
                let target = this;
                return Object.prototype.isTypeof(arguments[0], target);
            } else if (arguments.length === 2) {
                return Object.prototype.isTypeof(...arguments);
            }
        }}
    });
}

console.log(Object.prototype.typeof(NaN)) //gets 'NaN' as expected.
console.log(NaN.typeof()); //expecting 'NaN' not 'Number'

原因分析

核心问题出在原始值的自动装箱机制:

  • 当调用NaN.typeof()时,NaN是原始类型的数值,JavaScript会自动将其包装为Number对象(即“装箱”),此时方法内的this指向这个临时创建的Number实例,而非原始的NaN值。
  • 看typeof方法的逻辑:当arguments.length === 0时,target被赋值为this(也就是装箱后的Number对象)。此时Object.is(NaN, target)判断的是原始NaN和Number对象,结果为false,因此会执行target.constructor.name,返回'Number'。

而调用Object.prototype.typeof(NaN)时:

  • 你直接将原始NaN作为参数传入target,此时Object.is(NaN, target)判断成立,直接返回'NaN'。

补充说明:除了null和undefined,所有原始类型(字符串、数字、布尔值等)在调用原型方法时都会触发自动装箱,这是JavaScript的默认行为。

内容的提问来源于stack exchange,提问作者bho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 17:47:33