面试记录专刊:第四天

186 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情

今天复习计划:前端知识查漏补缺

一.前端知识

1. Script中的deferasync

  • script :会阻碍 HTML 解析,只有下载好并执行完脚本才会继续解析 HTML。

  • async script :解析 HTML 过程中进行脚本的异步下载,下载成功立马执行,有可能会阻断 HTML 的解析。

  • defer script:完全不会阻碍 HTML 的解析,解析完成之后再按照顺序执行脚本。

2. 如果减少回流与重绘

  • 最小化重绘与回流:如果无法避免要进行重绘或者回流,可将所有样式集中进行改变。
  • 批量操作DOM
  • 使用absoluteflexed使元素脱离文档流
  • 开启GPU加速:使用transformwill-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流程:

  1. 判断this是否为函数,判断conten是否不为空。
  2. 处理参数。
  3. 将function绑定至conten上,并记录执行结果。
  4. 删除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

  1. 创建一个空对象
  2. 绑定原型链: newObj.proto = object.prototype
  3. 绑定this指向
  4. 判断构造函数返回,如果为引用类型则返回,反之返回新建对象
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 的垃圾回收机制也是基于标记清除算法,不过对其做了一些优化。

  • 针对新生区采用并行回收。
  • 针对老生区采用增量标记与惰性回收。

二.算法

买卖股票的最佳时机

使用滑窗法,记录leftright指针。

二叉树的中序遍历

考查对二叉树的了解已经中序排序。

三.面经

暂无,明天约了2个面试,敬请期待!

四.其他

健身打卡:

3f3824fd142d2c3d01bfc67f85dd50e.jpg 英语打卡:

d153a0390cf5567f924c335d9e5d9dc.jpg

There is only one heroism in the world: to see the world as it`s and to love it