小红书前端开发面试题(温故而知新)

1、断点续传怎么做的?

答:断点续传是一种网络传输技术,可以在文件传输中出现中断后恢复传输而无需重新开始传输整个文件。这在文件传输较大、网络不稳定、带宽有限等情况下尤为重要。 通常情况下,实现断点续传需要客户端和服务端的相互配合。

以下是一般的实现步骤:

  • 客户端发起文件上传请求时,向服务端发送一个 HTTP 请求,包含文件名、文件大小等信息。
  • 服务端接收到请求后,根据文件名和文件大小创建一个空文件,并返回已经上传的文件大小,如果之前有部分数据已经上传过,那么服务端可以根据已上传的大小确定从哪个位置开始上传。
  • 客户端接收到服务端返回的已经上传的文件大小后,可以根据已上传的大小计算出下一次应该从哪个位置开始上传。
  • 客户端将文件切分为多个小块,每个小块的大小一般为几十 KB 或几百 KB,将每个小块的数据上传到服务端,并在每个小块的末尾添加一个分界符,标记上传结束。
  • 服务端接收到每个小块后,将其存储到文件对应的位置,等待下一次上传。
  • 如果上传过程中出现中断,客户端可以记录已经上传的文件大小和已经上传的小块数,下次上传时从上一次中断的位置开始继续上传。

总的来说,断点续传的实现需要客户端和服务端的相互配合,并需要考虑文件上传的稳定性和可靠性。

2、秒传怎么实现?

答:秒传是指上传一个文件时,如果已经存在相同的文件,就直接使用已经存在的文件,而不需要重新上传。实现秒传需要用到文件的唯一标识。

一种常见的实现方式是在上传文件时,先计算文件的哈希值或者MD5值,并将其作为文件的唯一标识。然后将该标识与后台数据库中已经存在的文件的标识进行比对。

如果存在相同的标识,说明该文件已经上传过,那么就直接使用已经存在的文件;

如果不存在相同的标识,说明该文件是一个新文件,那么就进行正常的上传操作。

在实现过程中,可以通过在前端计算文件哈希值或MD5值的方式,避免上传重复的文件,减少服务器的压力,提高文件上传的效率。

同时,后台服务器也需要维护一个文件信息的数据库,用于存储已经上传过的文件的唯一标识和存储路径等信息,以便实现秒传功能。

需要注意的是,文件的唯一标识需要具备唯一性和不可修改性,否则就无法实现秒传功能。

3、var let const 块级作用域。

答:在 JavaScript 中,var、let、const 都是声明变量的关键字,它们在作用域、赋值和重复声明方面有所不同。

  • var 声明变量的作用域是函数级别的,不受块级作用域的限制。在全局作用域中声明的变量会成为全局对象的属性。
  • let 声明的变量是块级作用域的,只在声明的块内有效。在 for 循环中,每次迭代都会创建一个新的变量。
  • const 声明的变量也是块级作用域的,和 let 类似,但是其值不能被重新赋值,只能被赋值一次。

在开发中,尽可能地使用 let 和 const 来代替 var避免变量提升和重复声明的问题,以及更好地控制变量作用域,提高代码的可读性和可维护性。

4、promise用过那些api?

答:在 JavaScript 中,Promise 是一种用于处理异步操作的对象。

它有一些常见的方法可以用来操作和处理异步操作

  • then():指定 Promise 成功(resolve)和失败(reject)时的回调函数,接受两个参数,一个是成功时的回调函数,一个是失败时的回调函数
  • catch():指定 Promise 拒绝(reject)时的回调函数,接收一个参数,即拒绝时的回调函数
  • finally():无论 Promise 成功还是失败,都会执行的回调函数,没有参数。
  • all():接收一个 Promise 数组,返回一个新的 Promise,当所有 Promise 都成功(resolve)时,返回值为数组,包含所有 Promise 成功时的结果;当其中任何一个 Promise 失败(reject)时,返回值为失败的 Promise 的值。
  • race():接收一个 Promise 数组,返回一个新的 Promise,当其中任何一个 Promise 成功(resolve)或失败(reject)时,返回值为该 Promise 的值。

除了上述方法外,Promise 还有一些静态方法,例如:

  • Promise.resolve():返回一个解决(resolve)的 Promise 对象,可以指定解决的值。
  • Promise.reject():返回一个拒绝(reject)的 Promise 对象,可以指定拒绝的原因。
  • Promise.allSettled():接收一个 Promise 数组,返回一个新的 Promise,当所有 Promise 都结束时,返回值为数组,包含所有 Promise 的状态和值。
  • Promise.any():接收一个 Promise 数组,返回一个新的 Promise,当其中任何一个 Promise 成功(resolve)时,返回值为成功的 Promise 的值;当所有 Promise 失败(reject)时,返回值为失败的 Promise 的值。

以上是 Promise 常见的方法和静态方法,可以用来管理异步操作的状态和结果。

5、Map和Object的区别。

答:在 JavaScript 中,Map 和 Object 都可以用来存储键值对。但是它们之间有几个关键的区别。 键的类型:Map 中的键可以是任意类型,包括原始类型和对象引用,而 Object 的键必须是字符串或者 Symbol 类型。

  • 插入顺序:Map 保留了插入顺序,因此在迭代 Map 时会按照插入顺序返回元素,而 Object 不保留插入顺序。
  • 大小:Map 可以使用 size 属性来获取元素的数量,而 Object 只能手动计算属性的数量。
  • 迭代:Map 支持 for-of 循环和 forEach 方法来迭代元素,而 Object 只能使用 for-in 循环来迭代属性,但是需要手动判断是否是自身属性而不是继承属性。
  • 性能:在非常大的数据集合下,Map 的查找和插入操作通常比 Object 更快。

综上所述,Map 更适合存储键值对,并需要保留插入顺序或使用非字符串类型作为键的情况,而 Object 则更适合存储属性。

6、vue2和vue3的双向绑定原理。

答:vue2中:使用Object.defineProperty对象以及对象属性的劫持+发布订阅模式,只要数据发生变化直接通知变化 并驱动视图更新。

vue3中的响应式采用了ES6中的 Proxy 方法。Proxy 对象用于定义基本操作的自定义行为(如属性查找、赋值、枚举、函数调用等)

详情参考: vue2和vue3的双向绑定原理_vue2和vue3双向绑定_m0_73464874的博客-CSDN博客

7、如何封装组件?

答:封装组件是前端开发中一个非常常见的任务,

以下是一些封装组件的方法:

  • 定义组件API:在设计组件时,首先需要考虑它的使用方式。定义组件API有助于其他开发人员快速理解如何使用组件,并确保组件在不同情况下具有一致的行为。
  • 使用props传递数据:在Vue中,组件通过props属性接收父组件传递的数据。在定义组件时,可以指定props属性的类型、默认值和必需性等。
  • 使用slot插槽分发内容:插槽是Vue中一种非常有用的功能,它可以允许组件的使用者插入内容到组件中。通过使用插槽,可以增加组件的灵活性,允许组件的使用者在不同的情况下自由地定制组件的外观和行为。
  • 使用事件向外通信:组件通常需要与外部环境进行交互。Vue中通过使用自定义事件可以实现组件向外部环境通信的功能。通过定义事件并在组件中触发该事件,可以允许外部环境对组件进行操作。
  • 使用mixins实现代码复用:Vue中提供了mixins功能,可以将一个或多个属性和方法混合到组件中。通过使用mixins,可以将常用的功能提取到可重用的模块中,减少代码的重复性。
  • 使用插件扩展Vue:Vue插件是一种可以扩展Vue功能的机制。通过编写插件,可以为Vue添加全局功能、指令、过滤器等。使用插件可以提高开发效率,减少代码量。
  • 使用动态组件:Vue中提供了动态组件的功能。通过使用动态组件,可以允许组件的使用者在运行时根据不同的条件选择不同的组件。

以上是一些封装组件的方法,当然具体的实现方式还需要根据具体的业务场景和组件功能来进行选择。

8、实现栈,有入栈出栈的方法,以及length属性。

答:栈是一种数据结构,它是一种线性的、具有一定特殊限制的数据结构,只能在一端进行插入和删除操作。栈的特点是后进先出,即最后压入的元素最先弹出。

class Stack
{
    constructor() { this.items = []; }                   // 入栈
    push(element) { this.items.push(element); }          // 出栈
    pop() { return this.items.pop(); }                   // 返回栈顶元素
    peek() { return this.items[this.items.length - 1]; } // 判断栈是否为空
    isEmpty() { return this.items.length == = 0; }       // 返回栈的长度
    get length() { return this.items.length; }
}

在这个栈实现中,我们使用了 push 方法来进行入栈操作,pop 方法来进行出栈操作,peek 方法来返回栈顶元素,isEmpty 方法来判断栈是否为空,length 属性来返回栈的长度。 使用这个栈实现的例子: 

const myStack = new Stack();
myStack.push(1);
myStack.push(2);
myStack.push(3);
console.log(myStack.length);    // 3
console.log(myStack.peek());    // 3
console.log(myStack.pop());     // 3
console.log(myStack.pop());     // 2
console.log(myStack.length);    // 1
console.log(myStack.isEmpty()); // false

针对以上内容,建议大家在已经实战过得基础上,去理解记忆,对于没有实战过的小伙伴,可以先了解。在以后的学习中,我们不仅要学会在实战中运用,更要在面试的时候将自己的知识技能流畅的表达出来,所以面试时候的语言组织和回答的条理性也是很重要的, 以后我会经常更新一些好的面试题,方便大家学习~ 

猜你喜欢

转载自blog.csdn.net/qq_41579104/article/details/131235631