读:《前端面试突破:JavaScript》
最近在准备面试,也算是重新学习一下,本书出自于leetcod,这篇文章就是记录一下阅读中遇到的问题或困惑
问题记录
-
1. 数字
0.1
对应的二进制是什么?需要深入学习IEEE 754 标准的双精度 64 位格式
-
2. 学到了
??=
、||=
和&&=
运算符 -
3.
typeof null
的值为object
这个bug是如何产生的?学习不同值类型的类型标签
在最初的js实现中,javascript的存储由类型标签+值
,其中object
的类型标签为000
,null
的类型标签也是000
。typeof在校验类型时,参照的便是类型标签,所以会由此误认为是object
- 4.
instanceof
实现原理?手写instanceof
实现。
简单例子
function instanceOf(left, right) {
if (typeof left !== "object" || left === null) {
return false;
}
let proto = Reflect.getPrototypeOf(left);
while (proto) {
if (proto === right.prototype) {
return true;
}
proto = Reflect.getPrototypeOf(proto);
}
return false;
}
-
5. 作用域分类:全局、函数、块级、模块
-
6. js中数据存储的方式,堆和栈具体是什么?
主要是想要写一段代码去模拟变量存储到堆和栈,以及从堆和栈中取出的操作。这里还需要考虑执行上下文和作用域链,暂时还没有找到相关的详细资料,所以先不写。
- 7. 手写一下基于原型的继承方式?
简述
其实也没啥好写的,就在这里简述一下:
原型链继承:
`SubType.prototype = new SuperType()`
将父类型的一个实例作为子类型的`prototype`
盗用构造函数:就是在子类函数中调用`SuperType.call(this)`
组合继承:就是将`原型链`与`盗用构造函数`两个相结合
寄生式继承:其实就是`Object.create`方法
寄生组合式继承:
子类函数中通过`盗用构造函数`模式获取父类的实例属性,
子类的`prototype`设置为`Object.create(SuperType.prototype)`
- 8. 手写一下使用
WeakMap
实现类的私有属性?
简单例子
/** 存放name私有属性的weakMap */
const nameVm = new WeakMap();
class Book {
constructor() {
// 初始化name私有属性
nameVm.set(this, "book");
}
// 获取name
getName() {
return nameVm.get(this);
}
// 设置name
setName(name) {
nameVm.set(this, name);
return true;
}
}
- 9.
bind
手写实现中为啥要new F
并将其作为新bound
函数的prototype
它这里主要是为了判断是不是在new
创建对象,在new
创建时,bind
传入的第一个对象将被忽略
- 10. 箭头函数不能绑定
this
,没有arguments
,也不能new
确实不能new
,但是不能说没有arguments
,它的arguments
和this
一样,是箭头函数所在的arguments
- 11. 手写一下节流的两种实现模式,定时器和时间戳模式
定时器模式
// 时间戳模式
const throttle = (fn, time) => {
let able = true;
return (...args) => {
if (able) {
able = false;
fn(...args);
setTimeout(() => {
able = true;
}, time);
}
};
};
时间戳模式
// 时间戳模式
const throttle = (fn, time) => {
let able = true;
let lastDateTime = 0;
return (...args) => {
const now = Date.now();
if (now - lastDateTime > time) {
able = false;
lastDateTime = now;
fn(...args);
}
};
};
- 12. 手写一下
Promise
实现
极简版本
class MyPromise {
constructor(func) {
this.state = "pending";
this.value = undefined;
this.resolvedCbs = [];
func(this.resolve.bind(this));
}
resolve(value) {
if (this.state === "pending") {
this.state = "resolved";
this.value = value;
const onResolve = this.resolvedCbs.shift();
if (onResolve) {
onResolve(value);
}
}
}
then(onResolve) {
return new MyPromise((resolve) => {
if (onResolve) {
if (this.state === "pending") {
this.resolvedCbs.push((value) => {
resolve(onResolve(value));
});
} else if (this.state === "resolved") {
resolve(onResolve(this.value));
}
} else {
resolve(undefined);
}
});
}
}
- 13. 手写一个可迭代
for of
的简单类
简单例子
class Forof {
constructor(limit) {
this.index = 0;
this.limit = limit;
}
[Symbol.iterator]() {
return this;
}
next() {
const res = { done: true, value: undefined };
if (this.index < this.limit) {
res.done = false;
res.value = this.index;
this.index++;
}
return res;
}
}
- 14. 手写一个
*
函数,并练习yield
和yield*
简单例子
function* forof(limit) {
let index = 0;
while (index < limit) {
yield index;
index++;
}
}
function* forofArr(limit) {
const arr = new Array(limit).fill(0).map((_, i) => i);
yield* arr;
}
- 15.
await
可以获取thenable
对象的值,如下例
简单例子
const a = {
then(cb) {
setTimeout(() => {
cb(1);
}, 1000);
},
};
(async function () {
const res = await a;
console.log("res", res);
})();
- 16. 学习一下
eval
方法
简单示例
// 可以获取脚本结果
const a = eval("2+2");
console.log("a", a);
// 模拟脚本,使用window对象
const script = "window.a = 1;console.log(window.a)";
// 定义window对象
const window = {};
// 调用脚本,脚本中可以获取本地的window对象
eval(`(function(window){${script}})(window)`);
console.log(eval([1, 2]));
// 非直接调用方式,脚本作用域在全局,不在当下
eval?.("console.log(window.a)");
- 17. 执行上下文和作用域链
这里的想法是通过代码模拟执行上下文和作用域链,如有幸学习到相关的内容再说。
-
18. 引用回收机制有循环引用的问题,标记清除有分代、增量和闲时收集三个优化策略
-
19. 研究一下怎么才能触发内存泄漏,目前是发现
console.log
会发生内存泄漏
简单例子
<body>
<div id="hallo">这是好的</div>
<script>
var theThings = [];
var replaceThing = function () {
theThings.push(
new Array(Math.floor(Math.random() * 1000000)).join("*")
);
// console.log("theThings.length", theThings);
};
setInterval(replaceThing, 1000);
document.getElementById("hallo").addEventListener("click", () => {
for (let n of theThings) {
console.log(n);
}
});
</script>
</body>
- 20. 学习一下
indexDB
的用法 - 21. 学习一下
Reflect
的方法 - 22. 学习一下
requirejs
和seajs
- 23. 实现一下大文件上传
- 24. 学习和实现一下单点登录