本文整理JavaScript中判断对象是否为空的多种方法,包括字符串比较、for in循环、jQuery封装、Object.getOwnPropertyNames及ES6的Object.keys。此外深入解析JSON.stringify的序列化特性,涵盖特殊值处理、toJSON函数执行及深拷贝陷阱,帮助开发者准确掌握对象检测与序列化机制。
var data = {};
var b = $.isEmptyObject(data); //true在实际开发中,判断对象是否为空是一个高频需求。本文将系统梳理实现这一目标的各种常用方案。
1、通过字符串比较判断
var data = {};
var b = JSON.stringify(data) == "{}";
console.log(b); // true2、利用 for in 循环遍历
var obj = {};
var b = function () {
for (var key in obj) {
return false;
}
return true;
};
console.log(b()); //true3、使用 jQuery 的 isEmptyObject() 方法
该方法是基于上述 for in 遍历逻辑的封装实现。
var data = {};
var b = $.isEmptyObject(data);
console.log(b); //true4、使用 Object.getOwnPropertyNames()
通过调用 Object 对象的 getOwnPropertyNames 方法,可以获取对象中所有属性名并返回一个数组。通过检查该数组的长度是否为 0,即可判断对象是否为空。
var data = {};
var arr = Object.getOwnPropertyNames(data);
console.log(arr.length == 0); // true5、使用 ES6 的 Object.keys()
此方法同样返回由对象自身可枚举属性名组成的数组,通过判断数组长度即可确定对象状态。
var data = {};
var arr = Object.keys(data);
console.log(arr.length == 0); // trueJSON.stringify() 扩展应用
JSON.stringify() 函数的主要作用是将 JavaScript 值转换为 JSON 格式的字符串。
语法定义如下:
JSON.stringify(value[, replacer[, space]])参数说明如下:
- value:必填参数,指代需要转换的 JavaScript 值,通常为目标对象或数组。
- replacer:可选参数,可以是函数或数组。若为函数,JSON.stringify 会针对每个成员的键和值调用该函数,并使用返回值替代原始值;若返回 undefined,则该成员被排除。根对象的键为空字符串 ""。若 replacer 为数组,则仅转换数组中包含的键对应的成员,且转换顺序与数组中键的顺序一致。
- space:可选参数,用于控制文本缩进、空格及换行。若为数字,返回值将在每个层级缩进指定数量的空格;若大于 10,则固定缩进 10 个空格。该参数也可接受非数字值,如制表符 \t。
- 返回值:返回包含格式化 JSON 文本的字符串。
JSON.stringify() 具备多项重要特性,具体如下:
第一大特性
当 undefined、任意函数以及 symbol 分别作为对象属性值、数组元素或单独值时,JSON.stringify() 会返回不同的结果。参考以下示例:
const data = {
a: "aaa",
b: undefined,
c: Symbol("dd"),
fn: function () {
return true;
},
};
JSON.stringify(data); // 输出:?
// "{"a":"aaa"}"原因在于,当 undefined、任意函数以及 symbol 作为对象属性值时,JSON.stringify() 会跳过(忽略)对这些值的序列化操作。
若将 undefined、任意函数以及 symbol 作为数组元素,结果会有何不同?
JSON.stringify([
"aaa",
undefined,
function aa() {
return true;
},
Symbol("dd"),
]); // 输出:?
// "["aaa",null,null,null]"原因在于,当这些值作为数组元素时,JSON.stringify() 会将它们序列化为 null。
此外,当 undefined、任意函数以及 symbol 作为单独值进行序列化时,JSON.stringify() 均返回 undefined。
JSON.stringify(function a() {
console.log("a");
});
// undefined
JSON.stringify(undefined);
// undefined
JSON.stringify(Symbol("dd"));
// undefined小结
- 当 undefined、任意函数以及 symbol 作为对象属性值时,JSON.stringify() 会跳过(忽略)它们的序列化。
- 当 undefined、任意函数以及 symbol 作为数组元素值时,JSON.stringify() 会将其序列化为 null。
- 当 undefined、任意函数以及 symbol 作为单独值进行序列化时,JSON.stringify() 均返回 undefined。
第二大特性
非数组对象的属性在序列化后的字符串中不保证以特定顺序出现。由于 JSON.stringify() 会忽略部分特殊值,因此序列化后的字符串顺序无法保证(数组除外)。
const data = {
a: "aaa",
b: undefined,
c: Symbol("dd"),
fn: function () {
return true;
},
d: "ddd",
};
JSON.stringify(data); // 输出:?
// "{"a":"aaa","d":"ddd"}"
JSON.stringify([
"aaa",
undefined,
function aa() {
return true;
},
Symbol("dd"),
"eee",
]); // 输出:?
// "["aaa",null,null,null,"eee"]"第三大特性
若转换值包含 toJSON() 函数,序列化结果将直接使用该函数的返回值,并忽略其他所有属性。
JSON.stringify({
say: "hello JSON.stringify",
toJSON: function() {
return "today i learn";
}
})
// "today i learn"第四大特性
JSON.stringify() 会正常序列化 Date 对象的值。
JSON.stringify({ now: new Date() });
// "{"now":"2019-12-08T07:42:11.973Z"}"第五大特性
NaN、Infinity 格式的数值以及 null 在序列化时均会被转换为 null。
JSON.stringify(NaN)
// "null"
JSON.stringify(null)
// "null"
JSON.stringify(Infinity)
// "null"第六大特性
布尔值、数字、字符串的包装对象在序列化过程中会自动转换为对应的原始值。
JSON.stringify([new Number(1), new String("false"), new Boolean(false)]);
// "[1,"false",false]"第七大特性
其他类型的对象,包括 Map、Set、WeakMap 和 WeakSet,仅会序列化其可枚举的属性。
// 不可枚举的属性默认会被忽略:
JSON.stringify(
Object.create(
null,
{
x: { value: 'json', enumerable: false },
y: { value: 'stringify', enumerable: true }
}
)
);
// "{"y":"stringify"}"第八大特性
深拷贝最简便的方式是 JSON.parse(JSON.stringify()),但由于序列化特性复杂,此方法存在诸多陷阱,例如循环引用问题。
// 对包含循环引用的对象(对象之间相互引用,形成无限循环)执行此方法,会抛出错误。
const obj = {
name: "loopObj"
};
const loopObj = {
obj
};
// 对象之间形成循环引用,形成闭环
obj.loopObj = loopObj;
// 封装一个深拷贝的函数
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}
// 执行深拷贝,抛出错误
deepClone(obj)
/**
VM44:9 Uncaught TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Object'
| property 'loopObj' -> object with constructor 'Object'
--- property 'obj' closes the circle
at JSON.stringify (<anonymous>)
at deepClone (<anonymous>:9:26)
at <anonymous>:11:13
*/总结
至此,关于 JavaScript 判断对象是否为空的几种常见方法介绍完毕。如需了解更多 JS 判断空对象的相关内容,请查阅本站往期文章或继续浏览后续文章,感谢大家的支持!