目录

1、空对象对应的字符串为 "{}"

2、for in

3、jquery 的 isEmptyObject()方法

4、Object.getOwnPropertyNames()

5、ES6 的 Object.keys()

JSON.stringify()扩展

1、第一大特性

小结

2、第二大特性

3、第三大特性

4、第四大特性

5、第五大特性

6、第六大特性

7、第七大特性

8、第八大特性

var data = {};
var b = $.isEmptyObject(data); //true

判断是否为空对象在实际开发中很常见,今天就让我们来整理一下有哪些方法吧。

1、空对象对应的字符串为 "{}"

var data = {};
var b = JSON.stringify(data) == "{}";
console.log(b); // true

2、for in

var obj = {};
var b = function () {
  for (var key in obj) {
    return false;
  }
  return true;
};
console.log(b()); //true

3、jquery 的 isEmptyObject()方法

这个方法是对第二个方法的封装。

var data = {};
var b = $.isEmptyObject(data);
console.log(b); //true

4、Object.getOwnPropertyNames()

Object 对象的 getOwnPropertyNames 方法,获取到对象中的属性名,存到一个数组中,返回数组对象,我们可以通过判断数组的 length 来判断此对象是否为空。

var data = {};
var arr = Object.getOwnPropertyNames(data);
console.log(arr.length == 0); // true

5、ES6 的 Object.keys()

此方法也是返回对象中属性名组成的数组。

var data = {};
var arr = Object.keys(data);
console.log(arr.length == 0); // true

JSON.stringify()扩展

JSON.stringify() 方法用于将 JavaScript 值转换为 JSON 字符串。
语法:

JSON.stringify(value[, replacer[, space]])

参数说明:

JSON.stringify()特性挺多的,具体如下:

1、第一大特性

对于 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]"

这是因为 undefined、任意的函数以及 symbol 作为数组元素值时,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

小结

2、第二大特性

非数组对象的属性不能保证以特定的顺序出现在序列化后的字符串中。因为 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"]"

JavaScript判断对象是否为空对象的几种方法

3、第三大特性

转换值如果有 toJSON() 函数,该函数返回什么值,序列化结果就是什么值,并且忽略其他属性的值。

JSON.stringify({
    say: "hello JSON.stringify",
    toJSON: function() {
      return "today i learn";
    }
  })
// "today i learn"

4、第四大特性

JSON.stringify() 将会正常序列化 Date 的值。

JSON.stringify({ now: new Date() });
// "{"now":"2019-12-08T07:42:11.973Z"}"

5、第五大特性

NaN 和 Infinity 格式的数值及 null 都会被当做 null。

JSON.stringify(NaN)
// "null"
JSON.stringify(null)
// "null"
JSON.stringify(Infinity)
// "null"

6、第六大特性

布尔值、数字、字符串的包装对象在序列化过程中会自动转换成对应的原始值。

JSON.stringify([new Number(1), new String("false"), new Boolean(false)]);
// "[1,"false",false]"

7、第七大特性

其他类型的对象,包括 Map/Set/WeakMap/WeakSet,仅会序列化可枚举的属性。

// 不可枚举的属性默认会被忽略:
JSON.stringify( 
    Object.create(
        null, 
        { 
            x: { value: 'json', enumerable: false }, 
            y: { value: 'stringify', enumerable: true } 
        }
    )
);
// "{"y":"stringify"}"

8、第八大特性

深拷贝最粗暴的方式是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
 */

发表回复