每日前端面试题-如何判断空对象,如何区分数据类型

一、如何判断空对象

①最常用 的是 Object.keys(obj).length === 0。它检查对象自身的、可枚举的属性名个数,性能好,能满足绝大多数业务场景。

②如果需要考虑不可枚举属性 (例如通过 Object.defineProperty 创建的属性),可以使用 Object.getOwnPropertyNames(obj).length === 0

③如果需要考虑最全面的情况(包括 Symbol 类型的属性键),则要使用 Reflect.ownKeys(obj).length === 0

④JSON.stringify(obj) === '{}' 方法虽然简单,但会忽略函数、undefined 等属性值,存在局限性,一般不推荐在严格的逻辑判断中使用。

1、JSON.stringify()

将对象转换为 JSON 字符串,然后判断其是否等于 '{}'

javascript 复制代码
const obj = {};
const isEmpty = JSON.stringify(obj) === '{}';
console.log(isEmpty); // true

const obj2 = { name: 'Tom' };
console.log(JSON.stringify(obj2) === '{}'); // false

缺点:

①性能问题:将整个对象序列化为字符串是一个相当耗时的行为

②如果属性值是函数,undefined,Symbol,JSON.stringigy()会忽略它们

javascript 复制代码
const obj = { a: undefined, b: function() {}, c: Symbol() };
console.log(JSON.stringify(obj) === '{}'); // true (但实际它有属性,所以判断不准确)
2、Object.keys() (最常用,兼顾性能和准确度)

Object.keys(obj) 返回对象自身可枚举属性名组成的数组。判断数组长度是否为 0 即可。

javascript 复制代码
const obj = {};
const isEmpty = Object.keys(obj).length === 0;
console.log(isEmpty); // true

const obj2 = { name: 'Tom' };
console.log(Object.keys(obj2).length === 0); // false

const obj3 = { a: undefined };
console.log(Object.keys(obj3).length === 0); // false (因为它确实有一个属性 'a')
3、Object.getOwnPropertyNames()可以发现不可枚举属性

返回所有属性名构成的数组,包含不可枚举属性,但是不包含Symbol类型的属性

javascript 复制代码
const obj = {};
Object.defineProperty(obj, 'hidden', {
  value: 'secret',
  enumerable: false // 设置为不可枚举
});

console.log(Object.keys(obj).length === 0); // true (keys 无法发现不可枚举属性)
console.log(Object.getOwnPropertyNames(obj).length === 0); // false (发现了不可枚举属性)
4、Reflect.ownKeys()(最彻底最全面的,返回所有属性名构成的数组)
javascript 复制代码
const obj = {};
const sym = Symbol('key');
obj[sym] = 'symbol value';

Object.defineProperty(obj, 'hidden', {
  value: 'secret',
  enumerable: false
});

console.log(Reflect.ownKeys(obj).length === 0); // false (包含了 Symbol 和不可枚举属性)
5、for...in(通常不推荐,但需要了解)

for...in 循环会遍历对象的可枚举属性 ,包括继承自原型链的属性。因此用它判断时,通常需要配合 hasOwnProperty 来过滤。

javascript 复制代码
function isEmpty(obj) {
            for(let key in obj) {
                if(obj.hasOwnProperty(key)) {
                    return false
                }
                return true
            }
        }
        const obj = {}
        console.log(isEmpty(obj))


        // 但是如果原型链上有可枚举属性
        const protoObj = {inherited: 'value'}
        // 以protoObj为原型创建新的对象
        const childObj = Object.create(protoObj)
        // true,(因为 childObj 自身没有属性,虽然原型链上有,但 hasOwnProperty 过滤掉了)
        console.log(isEmpty(childObj))

二、如何区分数据类型

javascript的数据类型分为两大类:

基本类型:string, number, boolean, undefined, null

引用类型:object, function, array, date

1、typeof操作符

typeof 适合判断 stringnumberbooleanundefinedsymbolbigintfunction。对于 null 和大部分对象类型,它只能返回 "object",无法进一步区分

javascript 复制代码
console.log(typeof 'hello');     // "string"
console.log(typeof 42);          // "number"
console.log(typeof true);        // "boolean"
console.log(typeof undefined);   // "undefined"
console.log(typeof Symbol());    // "symbol"
console.log(typeof 123n);        // "bigint"
console.log(typeof function(){});// "function" (函数是对象的一种,但 typeof 特殊处理)

// ---------- 著名的坑 ----------
console.log(typeof null);        // "object" (这是一个存在了20多年的bug)
console.log(typeof [1, 2, 3]);   // "object"
console.log(typeof {});          // "object"
console.log(typeof new Date());  // "object"
2、instanceof 操作符 (用于检查对象的具体类型)
javascript 复制代码
console.log([] instanceof Array);       // true
console.log([] instanceof Object);      // true (因为数组的原型链上也有 Object.prototype)
console.log({} instanceof Object);      // true
console.log(new Date() instanceof Date);// true
console.log(/regex/ instanceof RegExp); // true

// 基本类型用 instanceof 通常为 false
console.log('hello' instanceof String); // false (除非是 new String('hello') 创建的对象)
3、Object.prototype.toString.call() (终极方案,最准确)

这是最强大、最准确的类型判断方法。它可以返回任何数据类型的内部 [[Class]] 属性。

javascript 复制代码
const toString = Object.prototype.toString;

console.log(toString.call('hello'));      // "[object String]"
console.log(toString.call(42));           // "[object Number]"
console.log(toString.call(true));         // "[object Boolean]"
console.log(toString.call(undefined));    // "[object Undefined]"
console.log(toString.call(null));         // "[object Null]"
console.log(toString.call(Symbol()));     // "[object Symbol]"
console.log(toString.call(123n));         // "[object BigInt]"
console.log(toString.call([]));           // "[object Array]"
console.log(toString.call({}));           // "[object Object]"
console.log(toString.call(function(){})); // "[object Function]"
console.log(toString.call(new Date()));   // "[object Date]"
console.log(toString.call(/regex/));      // "[object RegExp]"
console.log(toString.call(new Error()));  // "[object Error]"
console.log(toString.call(document));     // "[object HTMLDocument]"
console.log(toString.call(globalThis));   // "[object global]" 或 "[object Window]"
相关推荐
一只理智恩1 小时前
基于 CesiumJS + React + Go 实现三维无人机编队实时巡航可视化系统
前端·人工智能·算法·golang·无人机
henry1010101 小时前
DeepSeek生成的HTML5小游戏 -- 投篮小能手
前端·javascript·css·游戏·html5
Zhu_S W1 小时前
EasyExcel:让Excel操作变得简单优雅
java·前端
GISer_Jing2 小时前
从零到架构师:Taro 全链路学习与实战指南
前端·react.js·taro
phltxy2 小时前
快速上手 ElementPlus:核心用法精讲
前端·javascript·vue.js
SuperEugene2 小时前
数组的 10 个常用操作:map / filter / reduce 实战套路
前端·javascript
晓得迷路了2 小时前
栗子前端技术周刊第 117 期 - TypeScript 6.0 Beta、webpack 2026 年路线图、React 最新生态调查报告结果...
前端·javascript·react.js
摇滚侠2 小时前
bootstrap 框架讲解-快速上手,最适合后端开发人员的bootstrap 保姆级使用教程
前端·bootstrap·html
lzhdim2 小时前
CSS实现毛玻璃模糊效果
前端·css