82. 面试官:js中常见的设计模式有哪些?

81期问题及答案

1. 请简述一下 == 和 === 的区别?

===== 是 JavaScript 中用于比较值的两个不同的操作符。它们之间的主要区别在于类型比较和类型转换:

  1. ==(相等运算符):

    例子:

    5 == 5 // true,数值相等
    '5' == 5 // true,字符串转换为数值后相等
    null == undefined // true,它们被认为是相等的特殊情况
    0 == false // true,布尔值 false 被转换为数值 0 后相等
  • == 用于比较两个值是否相等,但它不会强制要求它们的类型相同。

  • 如果操作数的类型不同,== 会尝试进行类型转换,然后再比较值。

  • 结果是一个布尔值,如果两个值相等,则返回 true,否则返回 false

===(严格相等运算符):

例子:

5 === 5 // true,数值相等且类型相同
'5' === 5 // false,类型不同
null === undefined // false,类型不同
0 === false // false,类型和值都不同
  • === 用于比较两个值是否严格相等,它要求两个值不仅要相等,还要类型相同。

  • 如果操作数的类型不同,=== 不会进行类型转换,直接返回 false

  • 结果是一个布尔值,只有在值和类型都相等的情况下才返回 true,否则返回 false

总结:

  • == 允许进行类型转换,可能导致意外的比较结果,因此在比较时要谨慎使用。

  • === 要求严格的类型和值匹配,通常更安全,因此在大多数情况下应该优先使用。

通常情况下,建议使用 === 进行比较,以避免类型转换带来的潜在问题。只有在确切知道需要类型转换的情况下才使用 ==

2. 数据去重有哪些方式,时间复杂度是多少?

在 JavaScript 中,数据去重有多种方式,每种方式都有不同的时间复杂度。以下是一些常见的数据去重方式以及它们的时间复杂度:

  1. 使用 Set(ES6):

    使用 JavaScript 的 Set 数据结构可以轻松实现数据去重。Set 仅存储唯一的值。

    const arr = [1, 2, 2, 3, 4, 4, 5];
    const uniqueArr = [...new Set(arr)];
  • 时间复杂度:O(n),其中 n 是数组的长度。

使用对象字面量(Object):

通过遍历数组,将数组元素作为对象属性存储,重复的元素会被覆盖。

const arr = [1, 2, 2, 3, 4, 4, 5];
const uniqueArr = Object.keys(arr.reduce((obj, item) => {
  obj[item] = true;
  return obj;
}, {}));
  • 时间复杂度:O(n),其中 n 是数组的长度。

使用 filter 方法:

使用数组的 filter 方法和 indexOf 来过滤重复元素。

const arr = [1, 2, 2, 3, 4, 4, 5];
const uniqueArr = arr.filter((item, index, array) => array.indexOf(item) === index);
  • 时间复杂度:O(n^2),其中 n 是数组的长度。因为在 filter 内部又进行了一次数组的遍历。

使用 reduce 方法:

使用数组的 reduce 方法来遍历数组,并将不重复的元素添加到新数组中。

const arr = [1, 2, 2, 3, 4, 4, 5];
const uniqueArr = arr.reduce((acc, item) => {
  if (!acc.includes(item)) {
    acc.push(item);
  }
  return acc;
}, []);
  • 时间复杂度:O(n^2),因为在 reduce 内部又进行了一次数组的遍历。

使用递归:

使用递归函数来遍历数组并去重。

function deduplicate(arr) {
  if (arr.length === 0) return [];
  const [head, ...tail] = arr;
  return [head, ...deduplicate(tail.filter(item => item !== head))];
}

const arr = [1, 2, 2, 3, 4, 4, 5];
const uniqueArr = deduplicate(arr);
  • 时间复杂度:O(n^2),因为递归函数内部进行了多次数组的遍历。

总结:

  • 使用 Set 或对象字面量是最有效的去重方法,时间复杂度为 O(n)。

  • 使用数组的 filterreduce 或递归方式效率较低,时间复杂度为 O(n^2)。

  • 选择适当的去重方法取决于你的数据规模和性能需求。在处理大型数组时,选择性能更高的方法非常重要。

3. 什么是类数组,怎么转换为正常的数组?

类数组(Array-like)是一种类似于数组的对象,它具有数值键(通常是从 0 开始的整数键)和 length 属性,但不具备数组的方法(例如 pushpopforEach 等)。在 JavaScript 中,常见的类数组包括函数的 arguments 对象、DOM 元素集合(例如 document.querySelectorAll 返回的结果)等。

要将类数组转换为正常的数组,你可以使用以下方法:

  1. 使用 Array.from 方法:

    Array.from 方法接受一个类数组对象作为参数,并返回一个新的数组。

    const arrayLike = { 0: 'a', 1: 'b', 2: 'c', length: 3 };
    const array = Array.from(arrayLike);
  2. 使用 Array.prototype.slice.call 方法:

    你可以通过 Array.prototype.slice.call 或简写为 [].slice.call 将类数组对象转换为数组。

    const arrayLike = { 0: 'a', 1: 'b', 2: 'c', length: 3 };
    const array = [].slice.call(arrayLike);
  3. 使用展开运算符 ...

    在支持展开运算符的环境中,你可以使用 ... 来转换类数组对象为数组。

    const arrayLike = { 0: 'a', 1: 'b', 2: 'c', length: 3 };
    const array = [...arrayLike];
  4. 使用循环手动转换:

    你还可以使用循环遍历类数组对象,并逐个添加到新的数组中。

    const arrayLike = { 0: 'a', 1: 'b', 2: 'c', length: 3 };
    const array = [];
    for (let i = 0; i < arrayLike.length; i++) {
      array.push(arrayLike[i]);
    }
  5. 使用 Array.prototype.concat 方法:

    你可以使用 concat 方法将类数组对象与一个空数组合并,从而得到一个新的数组。

    const arrayLike = { 0: 'a', 1: 'b', 2: 'c', length: 3 };
    const array = [].concat(arrayLike);

总之,这些方法可以让你将类数组对象转换为标准的 JavaScript 数组,以便可以使用数组的各种方法和特性。选择哪种方法取决于你的代码偏好和所在的环境。

82期

1. js中常见的设计模式有哪些?
2. instanceof 运算符的原理是什么?能否自己实现一个?
3. js中有哪些异步任务,和同步任务有什么区别?

上面问题的答案会在第二天的公众号推文中公布,如果觉得这篇文章对你有帮助,希望多多点赞收藏加关注,也希望分享给更多爱学习的小伙伴,你的肯定是我最大的动力。

学习不打烊,充电加油只为遇到更好的自己,每天早上9点纯手工发布面试题(死磕自己,愉悦大家) 希望大家在这浮夸的程序员圈里保持冷静,每天坚持花20分钟来学习与思考,在千变万化,类库层出不穷的今天,不要等到找工作时才狂刷题,提倡每日学习。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值