Appearance
实现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
}