持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情
今天复习计划:前端知识查漏补缺
一.前端知识
1. Script中的defer与async
-
script:会阻碍 HTML 解析,只有下载好并执行完脚本才会继续解析 HTML。 -
async script:解析 HTML 过程中进行脚本的异步下载,下载成功立马执行,有可能会阻断 HTML 的解析。 -
defer script:完全不会阻碍 HTML 的解析,解析完成之后再按照顺序执行脚本。
2. 如果减少回流与重绘
- 最小化重绘与回流:如果无法避免要进行重绘或者回流,可将所有样式集中进行改变。
- 批量操作DOM
- 使用
absolute或flexed使元素脱离文档流 - 开启GPU加速:使用
transform、will-change会为元素创建GPU图层,让动画元素在独立图层进行变化,可以避免产生回流与重绘。
3. 数据类型的判断
- typeOf 不能准确判断array、null
console.log(typeof 1); // number
console.log(typeof "1"); // string
console.log(typeof Symbol(1)); // symbol
console.log(typeof function a() {}); // funciton
console.log(typeof {}); // object
console.log(typeof []); // object
console.log(typeof null); // object
console.log(typeof undefined); // undefined
- Object.prototype.toString.call() 能用于判断所有原始数据类型
console.log(Object.prototype.toString.call(1)); // [object Number]
console.log(Object.prototype.toString.call('1')); // [object String]
console.log(Object.prototype.toString.call(function a(){})); // [object Function]
console.log(Object.prototype.toString.call({})); // [object Object]
console.log(Object.prototype.toString.call([])); // [object Array]
console.log(Object.prototype.toString.call(null)); // [object Null]
console.log(Object.prototype.toString.call(undefined)); // [object Undefined]
- instanceof 用于判断是否为类的实例。
function Student() {}
let a = new Student();
console.log(a instanceof Student); // true
如果判断一个变量arr是否为数组:
Array.isArray(arr)
Object.prototypeof.toString.call(arr) === '[object,array]'
arr instanceof Array
arr.__proto__ === Array.prototype
4. 深拷贝与浅拷贝
之所以存在深拷贝的问题是由于JS对引用型数据的存储导致,JS对于引用型的存储采用的堆存储。对于引用型数据的赋值只是指针的赋值,也就是浅拷贝。
手写深拷贝:
function deepClone(obj, map = new Map()) {
if (typeof obj !== "object") {
return obj;
}
let result = {};
if (map.has(obj)) {
return map.get(obj);
}
if (
Array.isArray(obj) ||
Object.prototype.toString.call(obj) === "[object Array]"
) {
result = [];
}
map.set(obj, result);
for (const key in obj) {
result[key] = deepClone(obj[key], map);
}
return result;
}
手写深拷贝需要注意的两个点:
- 引用型数据对于自身的引用
- 不可忽略数组型数据
5. 闭包
在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。可以在一个内层函数中访问到其外层函数的作用域。
简而言之:闭包即可以访问到外层函数作用域的内部函数
function Test() {
let obj = {};
return {
get() {
return obj;
},
set(value) {
obj = value;
},
};
}
const a = Test();
a.set({ 1: 1 });
6. bind、call、apply
- call
Function.prototype.myCall = function (content) {
if (typeof this !== "function") {
return new Error("type error");
}
let arg = [...arguments].slice(1);
content = content || window;
const fnSymbol = Symbol();
content[fnSymbol] = this;
const result = content[fnSymbol](...arg);
delete content[fnSymbol];
return result;
};
手写call流程:
- 判断this是否为函数,判断conten是否不为空。
- 处理参数。
- 将function绑定至conten上,并记录执行结果。
- 删除content上绑定的function并返回执行结果。
- apply
Function.prototype.myApply = function (content) {
if (typeof this !== "function") {
return new Error("type error");
}
content = content || window;
const arg = arguments[1]
return this.call(content, ...arg);
};
apply与call本质上没有任何区别,除了传参方式。bind的传参第二个参数为数组,稍微处理一下,其他流程与call相同。
- bind
Function.prototype.myBind = function (content) {
if (typeof this !== "function") {
return new Error("type error");
}
content = content || window;
const arg = [...arguments].slice(1);
const Fun = this;
return function () {
Fun.call(content, ...arg);
};
};
与call的流程差不多,只是bind与其他两个不同在于:bind返回的是函数,其他两个返回的是结果。
7. 手写New
- 创建一个空对象
- 绑定原型链: newObj.proto = object.prototype
- 绑定this指向
- 判断构造函数返回,如果为引用类型则返回,反之返回新建对象
function myNew(content) {
const obj = {};
obj.__proto__ = content.prototype;
const arg = [...arguments].slice(1);
const result = content.apply(obj, arg);
return typeof result === "object" ? result : obj;
}
8. 浏览器垃圾回收机制
V8引擎的垃圾回收机制:分成新生代、老生代。
- 新生代通过
scavenge算法,将空间分为使用区与空闲区。每次清道时,将仍在使用的对象从使用区移到空闲区,清空使用区并将两个区的定义互换。 - 老生代存储的是一些占用内存较大、存活时间长的对象。每次需要清道时,使用
标记清除法进行清除。
V8 的垃圾回收机制也是基于标记清除算法,不过对其做了一些优化。
- 针对新生区采用并行回收。
- 针对老生区采用增量标记与惰性回收。
二.算法
买卖股票的最佳时机
使用滑窗法,记录left及right指针。
二叉树的中序遍历
考查对二叉树的了解已经中序排序。
三.面经
暂无,明天约了2个面试,敬请期待!
四.其他
健身打卡:
英语打卡:
There is only one heroism in the world: to see the world as it`s and to love it