面试 JavaScript 框架八股文十问十答第九期

面试 JavaScript 框架八股文十问十答第九期

作者:程序员小白条,个人博客

相信看了本文后,对你的面试是有一定帮助的!关注专栏后就能收到持续更新!

⭐点赞⭐收藏⭐不迷路!⭐

1)对象创建的方式有哪些?

在 JavaScript 中,有几种方式可以创建对象:

  • 字面量方式: 使用花括号 {} 直接定义对象。

    const obj = { key1: 'value1', key2: 'value2' };
    
  • 构造函数方式: 使用构造函数创建对象,通过 new 关键字调用构造函数。

    function Person(name, age) {
      this.name = name;
      this.age = age;
    }
    
    const person = new Person('John', 25);
    
  • Object 构造函数: 使用 Object 构造函数创建对象。

    const obj = new Object();
    obj.key1 = 'value1';
    obj.key2 = 'value2';
    
  • Object.create() 方法: 使用 Object.create() 方法基于现有对象创建新对象。

    const parentObj = { key1: 'value1' };
    const childObj = Object.create(parentObj);
    

2)对象继承的方式有哪些?

在 JavaScript 中,对象继承可以通过以下方式实现:

  • 原型链继承: 子对象的原型指向父对象,通过原型链实现继承。

    function Parent() {
      this.property = 'value';
    }
    
    function Child() {
      // 子对象的原型指向父对象的实例
      Child.prototype = new Parent();
      this.childProperty = 'childValue';
    }
    
    const childObj = new Child();
    
  • 构造函数继承: 在子对象的构造函数中调用父对象的构造函数。

    function Parent() {
      this.property = 'value';
    }
    
    function Child() {
      // 在子对象构造函数中调用父对象构造函数
      Parent.call(this);
      this.childProperty = 'childValue';
    }
    
    const childObj = new Child();
    
  • 组合继承: 结合原型链继承和构造函数继承,利用原型链实现方法的继承,而通过构造函数实现属性的继承。

    function Parent() {
      this.property = 'value';
    }
    
    function Child() {
      Parent.call(this); // 构造函数继承属性
      this.childProperty = 'childValue';
    }
    
    Child.prototype = new Parent(); // 原型链继承方法
    
    const childObj = new Child();
    
  • ES6 的 class 继承: 使用 class 关键字定义类和继承关系。

    class Parent {
      constructor() {
        this.property = 'value';
      }
    }
    
    class Child extends Parent {
      constructor() {
        super(); // 调用父类构造函数
        this.childProperty = 'childValue';
      }
    }
    
    const childObj = new Child();
    

3)浏览器的垃圾回收机制

浏览器的垃圾回收机制负责自动管理内存,以便释放不再使用的对象,防止内存泄漏。主要的垃圾回收机制有两种:

  • 标记-清除(Mark and Sweep): 这是最常见的垃圾回收算法。它通过标记不再使用的对象,然后清除它们。垃圾收集器首先会标记所有的对象,然后遍历对象之间的引用关系,标记出活动对象。最后,清除阶段会删除所有没有标记的对象。
  • 引用计数: 这种算法会给对象分配一个引用计数,当对象被引用时,计数加一,当引用失效时,计数减一。当引用计数为零时,说明该对象不再被使用,可以被回收。然而,引用计数无法解决循环引用的问题,即使对象之间存在循环引用,它们的引用计数都不会降为零,导致无法被回收。

大多数现代浏览器使用标记-清除算法,结合一些优化策略,例如分代回收(Generational Collection)和增量回收(Incremental Collection),以提高垃圾回收的效率。

4)垃圾回收的概念

在计算机科学中,垃圾回收(Garbage Collection)是一种自动管理内存的机制,用于检测和释放不再被程序使用的内存空间,以防止内存泄漏和内存溢出。垃圾回收器负责追踪程序中的对象和数据结构的引用关系,标记那些不再被引用的对象,并在适当的时候释放它们所占用的内存空间,使得这些内存可以被重新利用。

5)垃圾回收的方式

在现代编程语言和运行时环境中,常见的垃圾回收方式包括:

  • 标记-清除(Mark and Sweep): 这是最常见的垃圾回收算法之一。它分为两个阶段:标记阶段和清除阶段。在标记阶段,垃圾回收器会遍历程序中的对象,并标记出所有仍然被引用的对象。在清除阶段,垃圾回收器会扫描堆内存,清除所有未被标记的对象。
  • 引用计数(Reference Counting): 这种算法会为每个对象维护一个引用计数,当对象被引用时,计数加一,当引用失效时,计数减一。当计数为零时,说明该对象不再被使用,可以被回收。然而,引用计数无法解决循环引用的问题,即使对象之间存在循环引用,它们的引用计数都不会降为零,导致无法被回收。
  • 复制(Copying): 这种算法将内存分为两个区域,通常是一个活动区和一个闲置区。在垃圾回收时,所有存活的对象都会被复制到闲置区,然后清空活动区。这种算法适用于内存碎片较多的情况,但会消耗更多的内存。
  • 标记-整理(Mark and Compact): 这种算法结合了标记-清除和复制两种方式的优点。首先标记所有活动对象,然后将它们整理到一端,清除其余的对象,从而减少内存碎片。
  • 增量式垃圾回收(Incremental Garbage Collection): 这种方式将垃圾回收的过程分成多个小步骤进行,每次只处理一部分对象,降低了单次垃圾回收的停顿时间,提高了程序的响应速度。

6)减少垃圾回收

为了减少垃圾回收的频率和影响,可以采取以下策略:

  • 避免创建不必要的对象: 尽量避免在循环或频繁执行的代码中创建临时对象,尤其是大对象。可以重用对象或使用对象池来减少对象的创建和销毁次数。
  • 使用对象池: 对于频繁创建和销毁的对象,可以使用对象池来重用对象,减少垃圾回收的压力。
  • 避免循环引用: 当存在循环引用时,即使对象不再被程序使用,其引用计数也不会降为零,导致无法被回收。因此,尽量避免循环引用的产生,或者手动断开循环引用。
  • 注意内存泄漏: 定期检查程序,确保没有内存泄漏问题,例如未及时清除的全局变量、事件监听器等。
  • 优化算法和数据结构: 使用合适的算法和数据结构可以减少内存的占用,降低垃圾回收的压力。

7)哪些情况会导致内存泄漏

内存泄漏通常是由以下情况导致的:

  • 未释放资源: 程序中未正确释放不再使用的内存、文件句柄、数据库连接等资源,导致这些资源无法被垃圾回收,从而造成内存泄漏。
  • 循环引用: 当两个或多个对象之间存在相互引用,而且这些对象之间都不再被程序使用时,由于彼此之间的引用计数不会降为零,这些对象就会被认为是活动对象,无法被垃圾回收,导致内存泄漏。
  • 全局变量: 如果程序中存在未及时清除的全局变量,这些变量会一直存在于内存中,直到程序结束,造成内存泄漏。
  • 未清理的定时器和事件监听器: 如果程序中创建了定时器或事件监听器,但在不再需要它们时未手动清除,这些定时器和监听器会继续存在,从而导致内存泄漏。
  • 未关闭的文件或网络连接: 如果程序中打开了文件或建立了网络连接,但在使用完毕后未正确关闭,这些文件或连接会一直占用内存,造成内存泄漏。

8)怎么解决内存泄漏问题

要解决内存泄漏问题,可以采取以下措施:

  • 及时释放资源: 在程序中使用完资源后,务必及时释放,包括内存、文件句柄、数据库连接等。
  • 避免循环引用: 注意避免对象之间的循环引用,如果确实需要循环引用,可以手动断开循环引用关系。
  • 优化全局变量的使用: 尽量避免使用全局变量,如果必须使用,确保在不再需要时及时清除。
  • 正确管理定时器和事件监听器: 在程序中使用定时器或事件监听器时,确保在不再需要时手动清除,以防止其持续占用内存。
  • 正确关闭文件和网络连接: 在程序中使用文件或网络连接时,确保在使用完毕后正确关闭,以释放占用的内存。
  • 使用内存泄漏检测工具: 可以使用内存泄漏检测工具来检测和诊断程序中的内存泄漏问题,并进行修复。

9)OPTIONS请求方法的作用?

OPTIONS 请求方法是用于获取目标资源所支持的通信选项,以检查服务器的性能。它的主要作用包括:

  • 查询服务器支持的请求方法: OPTIONS 请求通常会返回一个 Allow 头部,其中包含了服务器支持的所有 HTTP 请求方法,客户端可以根据这个信息来确定可以使用哪些方法与服务器进行交互。
  • 查询服务器支持的请求头部: OPTIONS 请求还可以返回一个 Access-Control-Allow-Headers 头部,其中包含了服务器支持的所有自定义请求头部,这对于跨域资源共享(CORS)是非常有用的。
  • 检查服务器是否支持跨域请求: 当客户端在发送跨域请求时,浏览器会先发送一个 OPTIONS 请求,以确定服务器是否允许该跨域请求,服务器会在响应中包含一些 CORS 相关的头部信息,例如 Access-Control-Allow-Origin,Access-Control-Allow-Methods 等。

10)常用的HTTP请求方法有哪些?

HTTP 协议定义了多种请求方法,常用的 HTTP 请求方法包括:

  • GET: 用于请求指定的资源。GET 请求应该只用于获取数据,并且不应该有副作用。
  • POST: 用于提交数据,通常会导致服务器状态的改变或副作用。POST 请求常用于创建新资源、提交表单数据等。
  • PUT: 用于向服务器更新资源,通常用于更新已存在的资源。
  • DELETE: 用于删除指定的资源。
  • PATCH: 用于对资源进行局部更新,只更新部分字段而不是整个资源。
  • OPTIONS: 用于获取目标资源所支持的通信选项,主要用于 CORS 和预检请求。
  • HEAD: 类似于 GET 请求,但服务器只返回头部信息,不返回实际内容,常用于检查资源是否存在或获取资源的元数据。
  • TRACE: 用于在客户端和服务器之间发送请求消息的回显测试,通常用于诊断和调试。
  • CONNECT: 用于将请求连接转换为透明的 TCP/IP 隧道,通常用于代理服务器。

开源项目地址:https://gitee.com/falle22222n-leaves/vue_-book-manage-system

已 300 + Star!

⭐点赞⭐收藏⭐不迷路!⭐

你可能感兴趣的:(面试八股文系列,面试,javascript,职场和发展,前端,项目实战,性能优化,八股文)