这是我参与更文挑战的第 20 天,活动详情查看 更文挑战
这个系列也没啥花头,就是来整平时面试的一些手写函数,考这些简单实现的好处是能看出基本编码水平,且占用时间不长,更全面地看出你的代码实力如何。一般不会出有很多边界条件的问题,那样面试时间不够用,考察不全面。
平时被考到的 api 如果不知道或不清楚,直接问面试官就行, api 怎么用这些 Google 下谁都能马上了解的知识也看不出水平。关键是在实现过程,和你的编码状态、习惯、思路清晰程度等。
注意是简单实现,不是完整实现,重要的是概念清晰和实现思路清晰,建议
先解释清除概念
=>写用例
=>写伪代码
=>再实现具体功能
,再优化
,一步步来。
20. 对象内存计算
是什么
问题很清楚就是给你一个对象,让你求出它所占用多大内存空间(字节),我们平时可以用 object-sizeof 这个库来计算
这个问题一般考察你的js内存基础知识
和写代码能力(递归),和各种边界条件的判断。
JavaScript 中的字符
采用 Unicode 来编码 ,也就是说,JavaScript 中的英文字符和中文字符
都会占用 2
个字节的空间大小。注意是单个字符。
string
类型内存空间是:单位长度2
字节(byte)number
类型内存空间是:8
字节boolean
类型内存空间是:4
字节
我们暂时不考虑 Symbol 等特殊类型
简单手写实现
实现
- 写个测试用例先
let testObj = {
a: 1,
kv: 'haha',
123: true,
d: [1, {f: 111}],
e: {a: 1, d: '2'}
}
计算下
- a: 1 => 键 'a':
2
B,值 1:8
B (B 是 Byte 字节) 共10B
- kv: haha => 键 'kv':
4
B,值 'haha':8
B (B 是 Byte 字节) 共12B
- 123: true =>
6B + 4B = 12B
因为 123 虽然是整数,但对象的 key 会转成字符串 所以占 6B - d: [1, {f: 111}] =>
2B + 8B + 2B + 8B = 20B
- e: {a: 1, d: '2'} =>
2B + 2B + 8B + 2B + 2B = 16B
最后总计: 10 + 12 + 10 + 20 + 16 = 68
B
- 实现主逻辑
代码思路很清晰,从主函数开始,只要注意以下2点就行
- 对于值为对象的情况,可能有重复引用的情况
- 对象键和值,都需要占用内存
这个过程我觉得应该看注释非常清楚,无非细心而已,思路倒不复杂。
let testObj = {
a: 1,
kv: 'haha',
123: true,
d: [1, {f: 111}],
e: {a: 1, d: '2'}
}
// 相同元素引用 Set、 或者用WeakSet
let usedReference = new Set()
// 计算数组的情况
function calcArrMemory(arr) {
// Array 有可能是下面两种形式, 所以还是需要递归
// [1, '2', true]
// [{a: 1}, [1, 2]]
// 使用 map / reduce 对每个元素实现计算后累计加和
return arr.map(memoryCalc).reduce((acc, cur) => acc + cur, 0)
}
// 计算对象的情况
function calcArrObject(obj) {
let res = 0;
// 对象键和值,都需要占用内存
let keys = Object.keys(obj)
for (let i = 0; i < keys.length; i++) {
let key = keys[i]
// 先算 key 的空间
res += memoryCalc(key)
// 对于值为对象的情况,可能有重复引用的情况
if (Object.prototype.toString.call(obj[key]) === '[object Object]') {
if (usedReference.has(obj[key])) {
continue;
}
// 用过的引用加入 Set
usedReference.add(obj[key])
}
// 再算出 value 空间
res += memoryCalc(obj[key])
}
return res
}
// 主函数,分情况讨论,遇到复杂情况递归计算
function memoryCalc(obj) {
const type = Object.prototype.toString.call(obj)
switch (type) {
// string 单位长度`2`字节
case '[object String]':
return obj.length * 2;
// number `8`字节
case '[object Number]':
return 8;
// boolean `4`字节
case '[object Boolean]':
return 4;
case '[object Null]':
return 0;
case '[object Undefined]':
return 0;
case '[object Array]':
return calcArrMemory(obj);
case '[object Object]':
return calcArrObject(obj);
default:
return 0;
}
}
console.log(memoryCalc(testObj))
// 68 和我们手算结果相同
另外向大家着重推荐下另一个系列的文章,非常深入浅出,对前端进阶的同学非常有作用,墙裂推荐!!!核心概念和算法拆解系列 记得点赞哈
今天就到这儿,想跟我一起刷题的小伙伴可以加我微信哦 点击此处交个朋友
Or 搜索我的微信号infinity_9368
,可以聊天说地
加我暗号 "天王盖地虎" 下一句的英文
,验证消息请发给我
presious tower shock the rever monster
,我看到就通过,加了之后我会尽我所能帮你,但是注意提问方式,建议先看这篇文章:提问的智慧