How to determine whether the object itself is empty in js?

How to determine whether the object itself is empty in js?

Prerequisite knowledge:

The enumerable property enumerable in the js object: used to control whether the described property will be included in the for...in loop (unless the property name is a Symbol). Specifically, if the enumerable of an attribute is false, the following three operations will not obtain the attribute.

  • for...incycle
  • Object.keysmethod
  • JSON.stringifymethod,

enumerable is false. Although the above operation cannot obtain the attribute, the value of the attribute can still be obtained.

for...inThe difference between and Object.keysis: the former includes the properties that the object inherits from the prototype object, while the latter only includes the properties of the object itself. If you need to get all the properties of the object itself, regardless of whether the enumerable value is true/false, you can use Object.getOwnPropertyNamesthe method.

How to determine whether an object is empty is a problem we often encounter in development. Today we will talk about several commonly used methods and how we use them in different scenarios.

  1. JSON.stringify

    JSON.stringifyThe method can serialize the object and convert it into the corresponding JSON format.

    const obj = {
          
          };
    
    console.log(JSON.stringify(obj) === '{}')  // true
    

    Disadvantages: If undefinedany function and symbol values ​​exist, they will be ignored (when appearing in attribute values ​​of non-array objects) or converted null(when appearing in arrays) during the serialization process.

    Example:

    const obj = {
          
          
    	a: undefined,
    	b: function() {
          
          },
    	c: Symbol()
    }
    console.log(JSON.stringify(obj) === '{}')  // true
    
  2. for…in combination hasOwnProperty

    Use for into traverse the current object:

    const obj = {
          
          }
    Object.prototype.a = 1
    
    function isEmptyObj(obj) {
          
          
      let flag = true
      for (let o in obj) {
          
          
        flag = false
        break
      }
      return flag
    }
    
    console.log(isEmptyObj(obj))  // false
    

    Since for inwhen performing object traversal, the properties on the object prototype will be traversed, and we only want to get its own properties, we can use hasOwnPropertyto achieve this, as follows:

    const obj = {
          
          }
    Object.prototype.a = 1
    
    function isEmptyObj(obj) {
          
          
      let flag = true
      for (let o in obj) {
          
          
        if (obj.hasOwnProperty(o)) {
          
          
          flag = false
          break
        }
      }
      return flag
    }
    
    console.log(isEmptyObj(obj))  // true
    

    Disadvantage: for inCannot traverse non-enumerable properties.

  3. Object.keys

    Object.keysWill return an array of enumerable properties of the object itself, without traversing the properties on the prototype.

    const obj = {
          
          }
    Object.prototype.a = 1
    
    console.log(Object.keys(obj).length === 0)  // true
    

    Disadvantages: Object.keysand for incan only traverse enumerable properties, not non-enumerable properties.

    We use Object.definePropertythe property enumerableto be set to falsetest, the example is as follows:

    const obj = {
          
          }
    Object.defineProperty(obj, 'a', {
          
          
      value: 1,
      enumerable: false
    })
    
    console.log(obj.a)  // 1
    console.log(isEmptyObj(obj))  // true
    console.log(Object.keys(obj).length === 0)  // true
    
  4. Object.getOwnPropertyNames

    Use Object.getOwnPropertyNamescan get an array composed of all attribute names of the object itself (including non-enumerable attributes).

    const obj = {
          
          }
    Object.defineProperty(obj, 'a', {
          
          
      value: 1,
      enumerable: false
    })
    
    console.log(Object.getOwnPropertyNames(obj))  // [ 'a' ]
    

    Disadvantages: You cannot get Symbolthe value as the attribute of the name. The above JSON.stringifyand methods cannot get for inthe value as the attribute of the name. Examples are as follows:Object.keysSymbol

    const a = Symbol()
    const obj = {
          
          
      [a]: 1
    }
    
    console.log(obj)  // { [Symbol()]: 1 }
    console.log(Object.getOwnPropertyNames(obj).length === 0)  // true
    console.log(JSON.stringify(obj) === '{}')  // true
    console.log(isEmptyObj(obj))  // true
    console.log(Object.keys(obj).length === 0)  // true
    
  5. Object.getOwnPropertyNames 结合Object.getOwnPropertySymbols

    It is known that Object.getOwnPropertyNamesthe only disadvantage is that you cannot get Symbolthe attribute with the value as the name, but Object.getOwnPropertySymbolsyou can only get Symbolthe attribute with the value as the name. Is the combination of the two a perfect solution? Let’s do a simple test:

    const a = Symbol()
    const obj1 = {
          
          
      [a]: 1
    }
    const obj2 = {
          
          b: 2}
    const obj3 = {
          
          }
    Object.defineProperty(obj3, 'a', {
          
          
      value: 1,
      enumerable: false
    })
    const obj4 = {
          
          }
    
    function getLength(obj) {
          
          
      return Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj)).length
    }
    
    console.log(getLength(obj1) === 0)  // false
    console.log(getLength(obj2) === 0)  // false
    console.log(getLength(obj3) === 0)  // false
    console.log(getLength(obj4) === 0)  // true
    

    After testing, the above method can indeed be solved, but it is more cumbersome. Is there a better method? The answer is yes.

  6. Reflect.ownKeys

    Reflect.ownKeysThe method returns an array composed of the properties of the target object itself. Its return value is equivalent to Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target)):

    const a = Symbol()
    const obj1 = {
          
          
      [a]: 1
    }
    const obj2 = {
          
          b: 2}
    const obj3 = {
          
          }
    Object.defineProperty(obj3, 'a', {
          
          
      value: 1,
      enumerable: false
    })
    const obj4 = {
          
          }
    
    console.log(Reflect.ownKeys(obj1).length === 0)  // false
    console.log(Reflect.ownKeys(obj2).length === 0)  // false
    console.log(Reflect.ownKeys(obj3).length === 0)  // false
    console.log(Reflect.ownKeys(obj4).length === 0)  // true
    

Summarize

When judging whether an object is empty, Reflect.ownKeysthe method is most perfect.

Guess you like

Origin blog.csdn.net/dfc_dfc/article/details/135441327