21. 面向对象基础「对象遍历的问题及解决方案」

1. 检测某个成员(属性/键) 是否属于这个对象,或者是否属于这个对象的私有属性

  • in:检测成员是否属于这个对象「特点:不论是私有属性,还是公有属性,只要有则检测结果就是true」

  • hasOwnProperty:用来检测当前成员是否为对象的私有属性「特点:只要是私有属性,结果才是true,哪怕有这个属性,但是属于公有的属性,结果也是 false」

function Fn() {
    this.x = 10
    this.y = 20
}

const f1 = new Fn()

console.log('x' in f1) // true
console.log(f1.hasOwnProperty('x')) // true

console.log('hasOwnProperty' in f1) // true
console.log(f1.hasOwnProperty('hasOwnProperty')) // false 不是它的私有属性,是它的公有属性
复制代码
  • 检测这个属性是否是这个对象的公有属性

    • 思路一:是它的属性,但是还不是私有的,那么一定是公有的。「BUG:如果某个属性即使私有的,也是公有的,则检测出来的结果是不准确的」。
    function hasPubProperty(obj, attr) {
        return (attr in obj) && (!obj.hasOwnProperty(attr))
    }
    复制代码
    • 思路二:真正的思路应该是检测原型上的属性,因为原型上的属性都是公有的。
    function hasPubProperty(obj, attr) {
    // Object.getPrototypeOf 获取当前对象的原型
    let proto = Object.getPrototypeOf(obj)
    while(proto) {
        // 依次查找原型链,直到找到 Object.prototype 为止
        if(proto.hasOwnProperty(attr)) {
            return true
        }
        proto = Object.getPrototypeOf(proto)
    }
        return false
    }
    复制代码

    2. for in 遍历问题

    • 问题1:

      • 很多对 对象 的操作时无法拿到 Symbol 属性的
      const sy = Symbol()
      const obj = {
          name: 'zhufeng',
          [sy]: 100
      }
      for(let key in obj) {
          console.log(key) // 无法遍历 Symbol 的私有属性
      }
      复制代码
      • 解决:只想遍历私有的,包含 Symbol 的
      // Object.keys 获取一个对象非 Symbol 的私有属性
      // Object.getOwnPropertySymbols 只获取 Symbol 的私有属性
      const keys = [
          ...Object.getOwnPropertyNames(obj),
          ...Object.getOwnPropertySymbols(obj)
      ]
      keys.forEach(key => {
          console.log(key, obj[key])
      })
      复制代码
    • 问题2:

      • 可以遍历到自己扩展的公共属性「内置的公共属性是不可枚举的(就是无法遍历到的)」
      const obj = {
          name: 'zhufeng'
      }
      obj.prototype.AAA = 100 // AAA 是 obj 的公共属性
      for(let key in obj) {
          console.log(key) // 把公有属性也遍历出来了
      }
      复制代码
      • 解决:能够避免遍历公共的
      for(let key in obj) {
          // 已经遍历到公共的,则私有已经遍历完,结束循环
          if(!obj.hasOwnProperty(key)) break
          console.log(key)
      }
      复制代码
    • 问题3:

      • 优先遍历数字属性,而且按照从小到大(不会严格按照属性书写的顺序)
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享