Skip to content

实现sizeOf函数,传入一个参数object,计算这个object占用了多少bytes?

  • number:64位存储,8个字节
  • string:每个长度2个字节
  • boolean:4个字节
js
function sizeOf (target) {
  const type = typeof target
  let size = 0

  switch (type) {
    case 'string': {
      const length = target.length
      return 2 * length
    }
    case 'number': {
      return 8
    }
    case 'boolean': {
      return 4
    }
    case 'symbol': {
      // Symbol.for()产生全局Symbol
      // 通过Symbol.keyFor(全局Symbol)会返回全局Symbol的标识,没有标识则返回字符串'undefined'
      // 非全局Symbol.toString() = 字符串'Symbol()',如果有标识()里就是标识,大小为标识的长度 * 2
      const isGlobalSymbol = Symbol.keyFor && Symbol.keyFor(target)
      return isGlobalSymbol 
        ? Symbol.keyFor(target).length * 2 
        : (target.toString().length - 8) * 2
    }
    case 'object': {
      if (target === null) return 0
      if (Array.isArray(target)) {
        // 如果是数组,每个元素递归
        size += target.map(sizeOf).reduce((total, cur) => {
          return total += cur
        }, 0)
      } else {
        // 如果是对象,计算对象的大小
        size += objectSize(target)
      }
      return size
    }
    default: {
      return 0
    }
  }
}

// WeakSet只能保存对象
const s = new WeakSet()

function objectSize (target) {
  let size = 0
  Object.keys(target).map(key => {
    // 对象每个属性都要计算进去
    size += sizeOf(key)
    // 如果属性值不为空,并且是对象
    if (target[key] !== null && typeof target[key] === 'object') {
      // 如果存在WeakSet中,说明存在多个引用变量指向同一个对象,不用再计算了,第一次已经计算过了
      if (s.has(target[key])) return
      // 如果不存在WeakSet中,此时要计算
      else {
        s.add(target[key])
        // size += sizeOf(target[key]) // 可以移到55
      }
    }
    // 能运行到这里,如果值是基本数据类型,要计算,如果值是对象,也是第一次遇到的对象,要计算
    size += sizeOf(target[key])
  })
  return size
}