1. 数组去重
功能:实现一个方法,去除数组中重复元素
原理:利用filter 和 indexOf通过判断元素第一次出现的索引值是否和当前索引来去重;
function uniqueArr(arr) {
let newArr = [];
newArr = arr.fliter((item, index)=> arr.indexOf(item) === index)
return newArr;
}
原理:set 是es6中的数据结构,自动去重,通过[...new Set(arr)]可以快速去重
function uniqueArr(arr) {
retun [... new Set(arr)];
}
还有其他方法就不一一列举
2.反转字符串
功能:实现一个方法,反转一个字符串(如:hello -》 olleh)
原理:利用split将字符串转为数组,然后数组利用reverse方法进行反转,然后再通过join合并回字符串;
function reverseString (string){
let newString = '';
newString = string.split('').reverse().join('')
return newString;
}
原理:for循环从尾部开始遍历,然后拼接成新字符串
function reverseString (string){
let reverseSring = '';
for(let i=string.length-1; i>=0; i--){
reverseString + = string[i];
}
return reverseSring;
}
3.深拷贝对象
功能:实现一个对象的深拷贝(处理嵌套对象和数组)
原理:
- 递归遍历对象的每个属性,对基本类型直接返回,引用类型继续递归。
- 使用
WeakMap记录已拷贝对象,解决循环引用问题。
function deepClone(obj, map = new WeakMap()) {
if (typeof obj !== 'object' || obj === null) return obj;
if (map.has(obj)) return map.get(obj); // 处理循环引用
const clone = Array.isArray(obj) ? [] : {};
map.set(obj, clone);
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
clone[key] = deepClone(obj[key], map);
}
}
return clone;
}
4.判断回文字符串
问题:判断一个字符串是否是回文(如 "A man, a plan, a canal: Panama")。
function isPalindrome(s) {
const clean = s.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();
return clean === clean.split('').reverse().join('');
}
// 或双指针优化
function isPalindrome(s) {
const clean = s.replace(/[^a-z0-9]/gi, '').toLowerCase();
let left = 0, right = clean.length - 1;
while (left < right) {
if (clean[left] !== clean[right]) return false;
left++;
right--;
}
return true;
}
原理:
- 先清理非字母数字字符并转为小写,再比较反转后的字符串。
- 双指针法减少时间复杂度到 O(n/2)。
5.找出数组中的最大差值
功能:给定一个数组,计算最大差值
原理:遍历数组,记录当前最小值,并计算当前数组最大值和最小值的差值,然后再更新最大差值;
function maxProfit (prices){
let minPrice = 0;
let maxProfit = 0;
for(let price of prices){
minPrice = Math.min(prices, price);
maxProfit = Math.max(maxProfit, price - minPrice)
}
retrun maxProfit;
}
6. 合并两个有序数组
问题:将两个有序数组合并为一个有序数组(假设第一个数组有足够空间)。
答案:
function merge(nums1, m, nums2, n) {
let i = m - 1, j = n - 1, k = m + n - 1;
while (j >= 0) {
nums1[k--] = (i >= 0 && nums1[i] > nums2[j]) ? nums1[i--] : nums2[j--];
}
}
原理:
- 从后向前遍历,避免覆盖
nums1的元素,比较两数组当前最大值,填入末尾。
7. 事件循环输出顺序
问题:以下代码的输出顺序是什么?
console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'));
console.log('4');
答案:1 → 4 → 3 → 2
原理:
- 同步代码(
1、4)最先执行。 - 微任务(Promise)优先于宏任务(setTimeout)执行。
8. 实现防抖(Debounce)
问题:手写防抖函数,限制高频触发的事件。
答案:
function debounce(fn, delay, immediate = false) {
let timer;
return function(...args) {
if (immediate && !timer) fn.apply(this, args);
clearTimeout(timer);
timer = setTimeout(() => {
if (!immediate) fn.apply(this, args);
timer = null;
}, delay);
};
}
原理:
- 每次触发时清除之前的定时器,重新计时,直到停止触发后执行最后一次。
9. 有效的括号
问题:判断字符串中的括号是否有效(如 "()[]{}" 有效,"(]" 无效)。
答案:
function isValid(s) {
const stack = [];
const map = { '(': ')', '[': ']', '{': '}' };
for (let char of s) {
if (map[char]) stack.push(char);
else if (map[stack.pop()] !== char) return false;
}
return stack.length === 0;
}
原理:
- 用栈结构处理左括号,遇到右括号时检查栈顶是否匹配。
10.手写Promise.all
功能:实现Promise.all的功能
原理:遍历Promise数组,统计完成数量,全部成功则返回结果数据,任一失败则立即拒绝;
function promiseAll(promises){
return new Promise(resole,reject=>{
const results = [];
let count = 0;
promises.forEach((p,i)=>{
Promise.resolve(p).then((res)=>{
results[i] = res;
count ++;
if(count===promises.length){
resole(esults)
}
}).catch(reject)
})
})
}