算法

https://juejin.cn/post/6844903793923096590#heading-5

1. 什么是Promise

promise是js提供的一种解决异步编程的新的方案。从语法上Promise是一个构造函数,用来封装异步操作并获取结果的一个类。
Promise内部只有三种状态,Pending,reject,resolve,而且状态是不可逆的。
Promise可以解决异步回调地狱的问题。主要的实现方式是通过返回一个新的promise,实现链式调用。然后通过状态管理实现回调函数的调用时机。
Promise属于一种微任务,在事件循环中,等同步执行完成之后,会从微任务队列中取出微任务调用,当当前循环的微任务执行完之后,会从宏任务队列中函数调用。直至下一轮事件循环开始。
Promise的错误处理
Error:所有错误的父类型
ReferenceError:引用变量不存在
TypeError:数据类型不正确
SyntaxError: 语法错误
RangeError:数据值不在其所允许的范围内

2. axios取消请求的原理

axios有个cancelToken,用来取消请求。其原理就是cancelToken里面有一个promise,然后被reslove的权利交给cancelToken,也就是说cancelToken类可以拿到promise的resolve。在调用source.cancel的时候,调用promise的reslove。然后当这个promise状态发生变化的时候,就调用request.abort取消请求

3. 怎么截取url的参数

window.location.search的值,该值包含?后面的
arr = window.location.search.substring(1).split(“&”)
arr.forEach, item.split(“=”)

4. es6新增特性

let/const
首先let const都有块级作用于,会形成一个暂时性死区。在未定义就去取值的时候会报错。const主要是用来定义常量的,当以了之后不能修改。Let是可以进行修改的。
async/await
async、await是结合generator以及promise实现的一个语法糖。利用iterator的next方法实现的。
实现原理是promise包裹generator,然后循环递归调用next,直到为done,就resolve最终结果。

  1. function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
  2. try {
  3. var info = gen[key](arg);
  4. var value = info.value;
  5. }
  6. catch (error) {
  7. reject(error); return;
  8. }
  9. if (info.done) {
  10. resolve(value);
  11. } else {
  12. Promise.resolve(value).then(_next, _throw);
  13. }
  14. }
  15. function _asyncToGenerator(fn) {
  16. return function () {
  17. var self = this, args = arguments;
  18. return new Promise(function (resolve, reject) {
  19. var gen = fn.apply(self, args);
  20. function _next(value) {
  21. asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
  22. }
  23. function _throw(err) {
  24. asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
  25. }
  26. _next(undefined);
  27. });
  28. };
  29. }
  30. function p() {
  31. return _p.apply(this, arguments);
  32. }
  33. function _p() {
  34. _p = _asyncToGenerator(function* () {
  35. yield console.log('xx');
  36. });
  37. return _p.apply(this, arguments);
  38. }
  39. p();

Symbol基础数据类型
array添加了map,filter,every,some,reduce
Set/Map
set存放有序序列,类似于数组,可以用来做数组去重。weakSet使用的弱引用,在垃圾回收的时候,其实还存在引用,该对象也可以被回收
Map存放的是键值对,weakMap同理weakSet
Iterator,Generator
Proxy/Reflect
Class类,通过extends实现继承
es5组合继承,组合寄生式继承

5. 什么是闭包

闭包的含义就是函数外部可以访问函数内部的属性
一般具体的表现形式就是一个function里面返回一个function,或者把function当做一个形参传给一个function
主要的目的是可以实现私有属性

6. 事件循环

7. 观察者模式和发布订阅者模式

8. 深入理解继承

9. 深浅拷贝

image.png
判断数据类型:
typeof 可以判断除null以外的基础类型和function
instanceof可以判断复杂类型,不能判断基础类型

  1. const myInstanceOf = (left, right) => {
  2. if (typeof left !== "object" || left === null) {
  3. return false;
  4. }
  5. let prop = Object.getPrototypeOf(left);
  6. while (true) {
  7. if (proto === null) {
  8. return false;
  9. }
  10. if (prop = right.prototype) {
  11. return true;
  12. }
  13. prop = this.getPrototypeOf(prop);
  14. }
  15. };

Object.prototype.toString.call();

  1. 浅拷贝
    1. Object.assign
    2. 扩展运算符
    3. Array.prototype.slice()
    4. Array.prototype.concat()
  2. 深拷贝

    1. JSON.parse(JSON.stringify(object))(忽略undefined,忽略symbol,不能处理正则,new Date,不能处理循环引用对象)
    2. 自己写的deepClone
      1. 如果是对象,并且不是null的时候,需要进行深度遍历,其他情况下直接返回value
      2. 循环引用问题,通过weakMap设置缓存,如果在缓存里面就直接取出,如果不在,就深度循环
      3. 对于symbol可以通过Reflect.ownKeys取到包含symbol的key值 ```html /**
      1. 对基础类型做一个最基本的一个拷贝
      1. 对引用类型开辟一个新的存储,并且拷贝一层对象属性
    • @param {} target / const shadowClone = (target) => { if (typeof target !== “object” || target === null) { return target; }

    const cloneTarget = Array.isArray(target) ? [] : {}; for (let prop in target) { if (target.hasOwnProperty(prop)) {

    1. cloneTarget[prop] = target[prop];

    } } return cloneTarget; };

    1. ```html
    2. /**
    3. * 1. 针对能够遍历对象的不可枚举属性以及 Symbol 类型,我们可以使用 Reflect.ownKeys 方法
    4. * 2. 当参数为 Date、RegExp 类型,则直接生成一个新的实例返回
    5. * 3. 利用 Object 的 getOwnPropertyDescriptors 方法可以获得对象的所有属性,以及对应的特性,顺便结合 Object 的 create 方法创建一个新对象,并继承传入原对象的原型链
    6. * 4. 利用 WeakMap 类型作为 Hash 表,因为 WeakMap 是弱引用类型,可以有效防止内存泄漏;如果存在循环,则引用直接返回 WeakMap 存储的值
    7. * @param {*} target
    8. */
    9. const deepClone = (target,hash = new WeakMap()) => {
    10. //1.普通类型
    11. if (typeof target !== "object" || target === null) {
    12. return target;
    13. }
    14. // 2.Date和 RegExp
    15. if (target instanceof Date) {
    16. return new Date(target);
    17. }
    18. if (target instanceof RegExp) {
    19. return new RegExp(target);
    20. }
    21. //4. 如果循环引用就返回obj,这里使用weakMap是为了防止内存泄漏
    22. if (hash.has(obj)) {
    23. return hash.get(obj);
    24. }
    25. //5. 运用Object.create创建一个新的obj
    26. let cloneObj = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));
    27. //3. Reflect.ownKeys获取不可枚举和Symbol类型
    28. for (let key of Reflect.ownKeys(obj)) {
    29. const item = obj[key];
    30. if (typeof item === 'object' && item !== null) {
    31. cloneObj[key] = deepClone(item, hash);
    32. } else {
    33. cloneObj[key] = obj[key];
    34. }
    35. }
    36. return cloneObj;
    37. };

    10.TS与JS

    TS是静态类型检查,JS是动态类型
    TS需要编译,JS不需要编译,浏览器直接识别
    TS有基础类型,String,Number,Object,Boolean,Null,Undefined,Void,any
    TS还有元组,interface,type,泛型
    泛型:我们在定义接口或者类的时候没有定义具体的类型,调用的时候才定义类型,用一个来表示泛型
    类型声明:兼容没有声明的包
    抽象类:能够定义具体的实现