答案是:js中判断原始类型用typeof(除null外均准确),遇"object"需排除null;最精准通用的是object.prototype.tostring.call(),可区分所有类型;instanceof适用于已知引用类型下的具体构造器判别。

判断一个变量是原始类型还是引用类型,关键不在“它看起来像什么”,而在于它的底层存储方式和行为特征。JS只有7种原始类型(string、number、boolean、null、undefined、symbol、bigint),其余全是引用类型——包括数组、函数、日期、正则、Map、Set、Promise等,它们都属于Object的派生或实例。
看 typeof 返回值,但要绕开 null 这个坑
typeof 是最快捷的初步判断方式,对大多数原始类型有效:
- 返回 "string" / "number" / "boolean" / "undefined" / "symbol" / "bigint" → 肯定是原始类型
- 返回 "function" → 是引用类型(Function 是特殊的对象)
- 返回 "object" → 不能直接下结论:可能是 null,也可能是真正的引用类型(如 {}、[]、new Date())
所以遇到 typeof x === 'object',必须额外排除 null:typeof x === 'object' && x !== null 才能安全认为它是引用类型。
用 Object.prototype.toString.call() 精准识别所有类型
这是最可靠、最通用的方法,能区分所有原始类型和引用类型的具体种类:
-
Object.prototype.toString.call('abc') === '[object String]'→ 原始字符串 -
Object.prototype.toString.call(new String('abc')) === '[object String]'→ 字符串对象(引用类型) Object.prototype.toString.call(null) === '[object Null]'Object.prototype.toString.call(undefined) === '[object Undefined]'-
Object.prototype.toString.call([]) === '[object Array]'→ 引用类型
所有结果都带 [object Xxx] 格式,原始类型和包装对象返回一致,且 null 和 undefined 也能正确区分。
结合 instanceof 判断具体引用类型(慎用于原始包装对象)
instanceof 适合检测是否为某构造函数的实例,但要注意:
-
[] instanceof Array→ true(推荐用于数组) -
{} instanceof Object→ true(但几乎所有引用类型都满足,区分度低) -
new String('a') instanceof String→ true,但'a' instanceof String→ false(原始字符串不是实例) -
null instanceof Object→ false,undefined instanceof Object→ false(安全)
它不适用于原始类型判断,只应在已确认是引用类型的前提下,进一步细分类型(如判别 Array、Date、RegExp 等)。
记住核心逻辑:值存栈里就是原始,地址存栈里就是引用
这不是语法技巧,而是内存机制决定的:
- 原始类型:变量直接持有值,赋值复制值,修改不影响原变量
- 引用类型:变量持有堆中对象的地址,赋值复制地址,通过任一变量修改属性,其他变量可见
- 函数参数都是按值传递——但对引用类型来说,“值”就是那个地址
理解这一点,比死记判断方法更能帮你避开陷阱,比如为什么 typeof null === 'object' 是历史 bug,为什么 const obj = {} 允许改属性却不允许重新赋值。











