683 字
3 分钟
JS判断空对象的常方法
一、常用方法
1. JSON.stringify(不可靠)
CAUTION但因为该方法序列化的某些策略,导致这种方法的判断很不可靠,后面有具体的测试用例
const res1 = JSON.stringify(emptyObj) === "{}";2. Reflect.ownKeys(推荐)
const res2 = Reflect.ownKeys(emptyObj).length === 0;3. Object.keys
const res3 = Object.keys(emptyObj).length === 0;4. Object.getOwnPropertyNames
const res4 = Object.getOwnPropertyNames(emptyObj).length === 0;5. for…in
let res5 = true;for (let key in emptyObj) { if (Object.prototype.hasOwnProperty.call(emptyObj, key)) { res5 = false; }}二、需要注意的地方
TIP先看正常的测试用例
// 测试对象const emptyObj = {};
// 1. JSON序列化(由于JSON.stringify自身的序列化策略,所以很不安全)const res1 = JSON.stringify(emptyObj) === "{}";console.log(res1);
// 2. Reflectconst res2 = Reflect.ownKeys(emptyObj).length === 0;console.log(res2);
// 3. Object.keys()const res3 = Object.keys(emptyObj).length === 0;console.log(res3);
// 4. Object.getOwnPropertyNamesconst res4 = Object.getOwnPropertyNames(emptyObj).length === 0;console.log(res4);
// 5. for...inlet res5 = true;for (let key in emptyObj) { if (Object.prototype.hasOwnProperty.call(emptyObj, key)) { res5 = false; }}console.log(res5);
/** * 结果: * 1 true * 2 true * 3 true * 4 true * 5 true */CAUTION异常的测试用例:
- 对象包含函数类型或者值为 undefined 的属性等
// ... 列举其中两种会让JSON.stringify出现异常的例子const obj = { a: function () {},};const obj2 = { b: undefined,};console.log(JSON.stringify(obj) === "{}", JSON.stringify(obj2) === "{}"); // true,true 但显然obj和obj2都不是空对象- 对象包含 symbol 的属性, 需要用 Reflect.keys 来判断, 其他几种都会出现异常
const key = Symbol();const obj = { [key]: "",};// ...console.log(Object.getOwnPropertyNames(emptyObj).length === 0); // true , 但显然obj并不是一个空对象
console.log(Reflect.ownKeys(emptyObj).length === 0); // false三、lodash 库的源码
import getTag from "./.internal/getTag.js";import isArguments from "./isArguments.js";import isArrayLike from "./isArrayLike.js";import isBuffer from "./isBuffer.js";import isPrototype from "./.internal/isPrototype.js";import isTypedArray from "./isTypedArray.js";
/** Used to check objects for own properties. */const hasOwnProperty = Object.prototype.hasOwnProperty;
/** * Checks if `value` is an empty object, collection, map, or set. * * Objects are considered empty if they have no own enumerable string keyed * properties. * * Array-like values such as `arguments` objects, arrays, buffers, strings, or * jQuery-like collections are considered empty if they have a `length` of `0`. * Similarly, maps and sets are considered empty if they have a `size` of `0`. * * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is empty, else `false`. * @example * * isEmpty(null) * // => true * * isEmpty(true) * // => true * * isEmpty(1) * // => true * * isEmpty([1, 2, 3]) * // => false * * isEmpty('abc') * // => false * * isEmpty({ 'a': 1 }) * // => false */function isEmpty(value) { // 处理null的情况 if (value == null) { return true; } // 对于类数组、数组、字符串、arguments对象、buffer等等 使用length属性判断 if ( isArrayLike(value) && (Array.isArray(value) || typeof value === "string" || typeof value.splice === "function" || isBuffer(value) || isTypedArray(value) || isArguments(value)) ) { return !value.length; } // 对于set或map的情况,通过size属性判断 const tag = getTag(value); if (tag == "[object Map]" || tag == "[object Set]") { return !value.size; } // 具有原型的普通对象 if (isPrototype(value)) { return !Object.keys(value).length; } for (const key in value) { if (hasOwnProperty.call(value, key)) { return false; } } return true;}
export default isEmpty;