美文网首页
关于Object属性的一些理解

关于Object属性的一些理解

作者: 哇塞田 | 来源:发表于2018-11-13 20:09 被阅读30次

    平时在业务写需求的时候总是会涉及到获取对象属性的需求。比如你可以像下面这么做:

        const obj = {
          prototype1: 1,
          prototype2: null,
          prototype3: 3
        }
        for (let key in obj) {
          console.log(key) // 'prototype1' 'prototype2' 'prototype3'
        }
    
    • hasOwnProperty
      但是如果你以为这样就万事大吉就错了,因为for in还可以查找遍历原型链上的属性,从而达到和你错误的预期。比如以下:
        Object.prototype.prototype4 = 4
        const obj = {
          prototype1: 1,
          prototype2: null,
          prototype3: 3
        }
        for (let key in obj) {
          console.log(key) // 'prototype1' 'prototype2' 'prototype3' 'prototype4'
        }
    

    所以我们用for in遍历对象的属性的时候需要过滤掉来自于原型链上的属性,hasOwnProperty方法接受一个字符串或者symbol用来返回对象上是否存在该属性,且该方法只会检测自身属性。所以代码可以作如下改造:

        Object.prototype.prototype4 = 4
        const obj = {
          prototype1: 1,
          prototype2: null,
          prototype3: 3
        }
        for (let key in obj) {
          if (obj.hasOwnProperty(key)) {
            console.log(key) // 'prototype1' 'prototype2' 'prototype3'
          }
        }
    

    但是如果你以为这样就安全就太年轻了,因为hasOwnProperty作为对象的一个属性来讲是可以被重写的,所以我们最好不要直接用对象自身的hasOwnProperty,而是如下:

        Object.prototype.prototype4 = 4
        const obj = {
          prototype1: 1,
          prototype2: null,
          prototype3: 3
        }
        for (let key in obj) {
          if (Object.hasOwnProperty.call(obj, key)) {
            console.log(key)
          }
        }
    
    • enumerable
      其实每个对象上面都会有很多属性,比如上面的hasOwnProperty也是对象的一个属性,那么为什么这些属性for in遍历不到呢?因为有些属性是不可枚举的,也就是说该属性的描述符enumerable为false,我们可以打印一下obj的一个属性来看一下该属性的描述符:
    console.log(Object.getOwnPropertyDescriptor(obj, 'prototype1'))
    

    我们可以看到打印了一个对象,其中enumerable为true。其实我们也可以设置对象的属性为不可枚举,然后在用for in看是否可以遍历的到:

        Object.prototype.prototype4 = 4
        const obj = {
          prototype1: 1,
          prototype2: null,
          prototype3: 3
        }
        Object.defineProperty(obj, 'prototype1', {
          enumerable: false
        })
        for (let key in obj) {
          if (Object.hasOwnProperty.call(obj, key)) {
            console.log(key)  // 'prototype2' 'prototype3'
          }
        }
    

    这里我们使用defineProperty去设置对象的属性的属性描述符,该方法第一个参数为对象,第二个参数为对象的属性,第三个参数为属性描述符。我们看到了prototype1没有被遍历到。

    • configurable value writable
      作为对象属性的属性描述符除了enumerable代表是否可枚举之外,还有configurable value writable这三个描述符,其中value很好理解,就是属性对应的值。configurable描述符为true的时候代表该属性可以被删除,writable为true代表可以修改该属性的value。
    • 结论
      我们获取对象属性的时候,最好使用Object.keys()方法。该方法会直接返回对象自身的所有可枚举属性的字符串数组。

    相关文章

      网友评论

          本文标题:关于Object属性的一些理解

          本文链接:https://www.haomeiwen.com/subject/scolfqtx.html