JS

  1. 事件循环机制是什么?为什么这么设计

    事件循环机制是js运行时处理异步任务的核心机制,它确保了异步任务能够以非阻塞的方式运行。整个事件循环机制可以看成由三部份组成:调用栈,Web Api, 任务队列。事件循环的工作就是当调用栈清空之后,从任务队列中不断取出回调函数推入调用栈执行。

    任务队列又可以分为宏任务队列和微任务队列,常见的宏任务有setTimeout, setInterval, io, ui渲染操作,常见的微任务有promise的回掉.then, await 之后的代码,MutationObserver。完整的事件循环机制周期就是从宏任务队列里取一个宏任务,例如我们的脚本的同步代码,然后执行完成之后检查微任务队列并执行和清空,然后如果有需要则会渲染页面,然后开始下一个循环。

    这其中有几个特殊的存在,requestIdleCallback,requestAnimationFrame,和UI渲染。UI渲染本身可以看作一个宏任务,但是它有自己的位置,通常在清空宏任务和微任务队列,下一个宏任务执行前。在ui渲染前,我们会执行requestAnimationFrame函数,而在这些执行完之后下一次循环开始前,浏览器会检查是否空闲来执行requestIdleCallback

    为什么这么设计:js设计之处为了简化开发,避免多线程的资源竞争和死锁等问题设计成了单线程,但是单线程最大的缺点就是会阻塞

  2. 深拷贝

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const getType = (obj) => {
    return Object.prototype.toString.call(obj)
    }
    const getInit = (target) => {
    const c = target.constructor
    return new c
    }
    const deepClone = (obj, map = new WeakMap()) => {
    if (!isObject())
    }
    1. 不同的类型
    2. 循环引用 weakmap
    3. 继承:Object.create()但是要注意map/set
    4. 函数最好不处理,涉及curry function
  3. 继承

    1. 原型链继承(直接修改构造函数的prototype),作为原型的 Super 实例本身没有 constructor 属性,并不是它上面有个错误的属性才导致 Sub 的 constructor 错误的
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function Super (){
    this.superValue = 1
    }
    Super.prototype.getSuperValue = function(){
    console.log(this.superValue)
    }
    function Sub(){
    this.subValue = 0
    }
    Sub.prototype = new Super()
    // 手动修正构造函数指针
    Sub.prototype.constructor = Sub
    const instance = new Sub()
    instance.getSuperValue() // 1
    1. 借用构造函数继承, 无法继承父类原型上的属性或方法,父类的构造函数并不是被new调用而是被当作普通函数调用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    function Super (){
    this.colors = ['red', 'blue', 'yellow']
    }
    Super.prototype.count = 1
    function Sub(){
    Super.call(this)
    }
    const instance1 = new Sub()
    const instance2 = new Sub()
    instance1.colors.push('black')
    console.log(instance1.count) // undefined
    console.log(instance1.colors) // ['red', 'blue', 'yellow','black']
    console.log(instance2.colors) // ['red', 'blue', 'yellow']
    1. 组合继承
    1
    // 结合上面两种 当时这样父类要被调用两次
    1. 原型式继承
    1
    2
    3
    4
    5
    6
    7
    8
    function object(obj){
    function F(){}
    F.prototype = obj;
    return new F();
    }
    // 其实就是 Object.create 的简易实现,以现有对象为原型

    Object.create会创建一个新的空对象让后将该对象的 __proto__指向传入的参数
    1. 寄生继承
    1
    2
    3
    4
    5
    6
    7
    8
    function createAnother(original){
    var clone = Object.create(original); // 通过调用 object() 函数创建一个新对象
    clone.sayHi = function(){ // 以某种方式来增强对象
    alert("hi");
    };
    return clone; // 返回这个对象
    }
    // 相当于在 clone 这个实例上增加属性和方法
    1. 寄生组合继承
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    function SubType(name, age) {
    SuperType.call(this, name)
    this.age = age
    }

    SuperType.prototype.sayName = function(){
    alert(this.name)
    }

    function SuperType(name) {
    this.name = name
    }

    inheritPrototype(SubType, SuperType)

    function inheritPrototype(subType, superType){
    var prototype = Object.create(superType.prototype);
    // prototype: { __proto__: { sayName } }
    prototype.constructor = subType;
    // prototype: { __proto__: { sayName }, constructor: subType }
    subType.prototype = prototype;
    }
    1. class extends 关键字
    1
    super()
  4. 设计模式

    1. 策略模式。代替冗长的if-else,常见角色权限判断

    2. 发布订阅模式。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      class EventEmitter(){
      this.events = {}
      on(e, listener){}
      emit(e, ...args){}
      }
      class Publisher() {
      EventEmitter.trigger(e)
      }
      class Subscriber(){
      EventEmitter.on(e, () => {})
      }
  5. 观察者模式。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Observer() {
    this.observerList = []
    notify(){
    this.observerList.forEach((i) => i.update())
    }
    }
    class Subject() {
    update(){}
    }
  6. 装饰器模式。增强

  7. 适配器模式

  8. 代理模式,vue proxy

  9. 责任链模式,分步表单,中间件,异常处理

  10. 工厂模式

  11. 单例模式

  12. 作用域

  13. new 关键字

    1. 创建新的空对象
    2. 将空对象__proto__连接到构造函数prototype
    3. 绑定this函数执行构造函数
    4. 返回新对象,除非构造函数显示返回了非原始值
  14. 箭头函数和 function的区别

    1. 箭头函数没有 this,内部的 this 指向外层作用域的this,不能作为构造函数,也不能bind。function的this是动态的
    2. 箭头函数没有arguments对象,访问参数用…rest;function有arguments对象
  15. link标签的preload和prefetch的区别

    1. preload的资源优先级高,浏览器会立即下载,等待被使用
    2. prefetch是预先加载未来可能需要的资源,优先级低
  16. 装饰器是什么

    1. 装饰器本质是一个高阶函数,它接收一个函数/类作为参数,返回一个新的函数/类
    2. 多个装饰器是从下到上,从右到左执行

感谢您的支持 | Thank you for supporting

JS
http://example.com/2025/10/17/1JS/
作者
Eli Bi
发布于
2025年10月17日
更新于
2025年10月20日
许可协议