81期问题及答案
1. 请简述一下 == 和 === 的区别?
==
和 ===
是 JavaScript 中用于比较值的两个不同的操作符。它们之间的主要区别在于类型比较和类型转换:
==
(相等运算符):例子:
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 中,数据去重有多种方式,每种方式都有不同的时间复杂度。以下是一些常见的数据去重方式以及它们的时间复杂度:
使用 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)。
使用数组的
filter
、reduce
或递归方式效率较低,时间复杂度为 O(n^2)。选择适当的去重方法取决于你的数据规模和性能需求。在处理大型数组时,选择性能更高的方法非常重要。
3. 什么是类数组,怎么转换为正常的数组?
类数组(Array-like)是一种类似于数组的对象,它具有数值键(通常是从 0 开始的整数键)和 length
属性,但不具备数组的方法(例如 push
、pop
、forEach
等)。在 JavaScript 中,常见的类数组包括函数的 arguments
对象、DOM 元素集合(例如 document.querySelectorAll
返回的结果)等。
要将类数组转换为正常的数组,你可以使用以下方法:
使用
Array.from
方法:Array.from
方法接受一个类数组对象作为参数,并返回一个新的数组。const arrayLike = { 0: 'a', 1: 'b', 2: 'c', length: 3 }; const array = Array.from(arrayLike);
使用
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);
使用展开运算符
...
:在支持展开运算符的环境中,你可以使用
...
来转换类数组对象为数组。const arrayLike = { 0: 'a', 1: 'b', 2: 'c', length: 3 }; const array = [...arrayLike];
使用循环手动转换:
你还可以使用循环遍历类数组对象,并逐个添加到新的数组中。
const arrayLike = { 0: 'a', 1: 'b', 2: 'c', length: 3 }; const array = []; for (let i = 0; i < arrayLike.length; i++) { array.push(arrayLike[i]); }
使用
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分钟来学习与思考,在千变万化,类库层出不穷的今天,不要等到找工作时才狂刷题,提倡每日学习。