手写深拷贝
function deepClone(obj) {
// 处理基础数据类型和函数
if (obj === null || typeof obj !== 'object') {
return obj;
}
// 处理数组
if (Array.isArray(obj)) {
return obj.map(item => deepClone(item));
}
// 处理对象
const clonedObj = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
clonedObj[key] = deepClone(obj[key]);
}
}
return clonedObj;
}
const original = {
a: 1,
b: [2, 3],
c: { d: 4 }
};
const copy = deepClone(original);
console.log(copy);
冒泡排序
对于一组要排序的元素列,依次比较相邻的两个数,将比较小的数放在前面,比较大的数放在后面,如此继续,直到比较到最后的两个数,将小数放在前面,大数放在后面,重复步骤,直至全部排序完成
function bubbleSort(arr) {
let n = arr.length;
for (let i = 0; i < n - 1; i++) {
for (let j = 0; j < n - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
// 交换
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
}
return arr;
}
const array = [64, 34, 25, 12, 22, 11, 90];
console.log(bubbleSort(array)); // 输出: [11, 12, 22, 25, 34, 64, 90]
快速排序
快速排序是对冒泡排序的一种改进,通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按照此方法对这两部分数据分别进行快速排序
function quickSort(arr) {
if (arr.length <= 1) {
return arr; // 基本情况:数组为空或只有一个元素时,直接返回
}
const pivot = arr[arr.length - 1]; // 选择最后一个元素作为基准
const left = []; // 存放小于基准的元素
const right = []; // 存放大于基准的元素
for (let i = 0; i < arr.length - 1; i++) {
if (arr[i] < pivot) {
left.push(arr[i]); // 小于基准的元素放左边
} else {
right.push(arr[i]); // 大于基准的元素放右边
}
}
// 递归排序左边和右边,并结合基准
return [...quickSort(left), pivot, ...quickSort(right)];
}
const array = [3, 6, 8, 10, 1, 2, 1];
const sortedArray = quickSort(array);
console.log(sortedArray); // [1, 1, 2, 3, 6, 8, 10]
深度平铺数组
function flattenArray(arr) {
return arr.reduce((acc, val) => {
return Array.isArray(val)
? acc.concat(flattenArray(val)) // 递归调用
: acc.concat(val); // 直接添加元素
}, []);
}
const nestedArray = [1, [2, [3, 4], 5], 6, [7, 8]];
const flatArray = flattenArray(nestedArray);
console.log(flatArray); // [1, 2, 3, 4, 5, 6, 7, 8]
数组去重
方法一:
const uniqueArray = arr => [...new Set(arr)];
const arr = [1, 2, 2, 3, 4, 4, 5];
const result = uniqueArray(arr);
console.log(result); // [1, 2, 3, 4, 5]
方法二:
const uniqueArray = arr => arr.filter((value, index) => arr.indexOf(value) === index);
const arr = [1, 2, 2, 3, 4, 4, 5];
const result = uniqueArray(arr);
console.log(result); // [1, 2, 3, 4, 5]
方法三:
const uniqueArray = arr => arr.reduce((acc, value) => {
if (!acc.includes(value)) {
acc.push(value);
}
return acc;
}, []);
const arr = [1, 2, 2, 3, 4, 4, 5];
const result = uniqueArray(arr);
console.log(result); // [1, 2, 3, 4, 5]
将数字转化为千分位格式
方法一:
const formatNumber = num => num.toLocaleString();
const num = 1234567.89;
const result = formatNumber(num);
console.log(result); // "1,234,567.89"
方法二:
const formatNumber = num => {
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
};
const num = 1234567.89;
const result = formatNumber(num);
console.log(result); // "1,234,567.89"
计算函数执行所花费的时间
方法一:
function exampleFunction() {
// 模拟一些耗时操作
for (let i = 0; i < 1e6; i++) {}
}
console.time('Function Execution Time');
exampleFunction();
console.timeEnd('Function Execution Time'); // 输出函数执行所花费的时间
方法二:
function exampleFunction() {
// 模拟一些耗时操作
for (let i = 0; i < 1e6; i++) {}
}
const start = performance.now();
exampleFunction();
const end = performance.now();
console.log(`Function Execution Time: ${end - start} milliseconds`);
解析url参数
方法一:
const url = 'https://example.com/?name=John&age=30';
const params = new URL(url).searchParams;
const name = params.get('name'); // 'John'
const age = params.get('age'); // '30'
console.log(name, age);
方法二:
function getQueryParams(url) {
const queryString = url.split('?')[1];
if (!queryString) return {};
return queryString.split('&').reduce((params, param) => {
const [key, value] = param.split('=');
params[decodeURIComponent(key)] = decodeURIComponent(value || '');
return params;
}, {});
}
const url = 'https://example.com/?name=John&age=30';
const params = getQueryParams(url);
console.log(params); // { name: 'John', age: '30' }
方法三:
使用 qs 这个库
const qs = require('qs');
const url = 'https://example.com/?name=John&age=30';
const queryString = url.split('?')[1]; // 获取查询字符串部分
const params = qs.parse(queryString);
console.log(params); // { name: 'John', age: '30' }
合并对象
方法一:
const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };
const merged = Object.assign({}, obj1, obj2);
console.log(merged); // { a: 1, b: 3, c: 4 }
方法二:
const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };
const merged = { ...obj1, ...obj2 };
console.log(merged); // { a: 1, b: 3, c: 4 }
方法三:
const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };
const merged = [obj1, obj2].reduce((acc, obj) => {
Object.entries(obj).forEach(([key, value]) => {
acc[key] = value;
});
return acc;
}, {});
console.log(merged); // { a: 1, b: 3, c: 4 }
对象转换为键值对
方法一:
const obj = { a: 1, b: 2, c: 3 };
const entries = Object.entries(obj);
console.log(entries); // [['a', 1], ['b', 2], ['c', 3]]
方法二:
const obj = { a: 1, b: 2, c: 3 };
const entries = Object.keys(obj).map(key => [key, obj[key]]);
console.log(entries); // [['a', 1], ['b', 2], ['c', 3]]
方法三:
使用 for...in 循环
const obj = { a: 1, b: 2, c: 3 };
const entries = [];
for (const key in obj) {
entries.push([key, obj[key]]);
}
console.log(entries); // [['a', 1], ['b', 2], ['c', 3]]
散列算法
散列算法(Hashing)是一种将输入数据(通常是任意大小)转换成固定大小的输出(散列值或哈希值)的算法。它广泛应用于数据结构(如哈希表)、数据完整性验证、数字签名等
特点:
- 固定长度输出;无论输入数据多大,输出都是固定长度
- 快速计算;对输入数据进行哈希计算的速度很快
- 抗碰撞;不同的输入应进行产生不同的输出
- 不可逆;从哈希值不能反推原始输入
方法一:
简单的 SHA-256 散列算法实现,使用 `crypto` 模块(Node.js 环境)
const crypto = require('crypto');
function hashData(data) {
return crypto.createHash('sha256').update(data).digest('hex');
}
const data = 'Hello, world!';
const hashValue = hashData(data);
console.log(hashValue); // 输出哈希值
方法二:
使用 Web Crypto API(浏览器环境)
async function hashData(data) {
const encoder = new TextEncoder();
const dataBuffer = encoder.encode(data);
const hashBuffer = await crypto.subtle.digest('SHA-256', dataBuffer);
const hashArray = Array.from(new Uint8Array(hashBuffer));
return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}
hashData('Hello, world!').then(hashValue => {
console.log(hashValue); // 输出哈希值
});
幂集
幂集是一个集合的所有子集的集合,包括空集和自身
通过递归来计算
function powerSet(arr) {
const result = [];
function generate(subset, index) {
if (index === arr.length) {
result.push(subset);
return;
}
generate(subset, index + 1); // 不包含当前元素
generate([...subset, arr[index]], index + 1); // 包含当前元素
}
generate([], 0);
return result;
}
const set = [1, 2, 3];
const pSet = powerSet(set);
console.log(pSet);
// 输出[ [], [ 1 ], [ 2 ], [ 1, 2 ], [ 3 ], [ 1, 3 ], [ 2, 3 ], [ 1, 2, 3 ] ]
最大公约数
最大公约数是能整除两个或多个整数的最大正整数
使用欧几里得算法来计算最大公约数
function gcd(a, b) {
while (b !== 0) {
const temp = b;
b = a % b;
a = temp;
}
return a;
}
const num1 = 48;
const num2 = 18;
const result = gcd(num1, num2);
console.log(result); // 输出 6
生成斐波那契数组
斐波那契数组是由斐波那契数列生成的数组,数列中的每个数都是前两个数的和,通常以 `0` 和 `1` 开始。数列的前几个数是:`0, 1, 1, 2, 3, 5, 8, 13, ...`
function generateFibonacci(n) {
const fib = [0, 1];
for (let i = 2; i < n; i++) {
fib[i] = fib[i - 1] + fib[i - 2];
}
return fib.slice(0, n);
}
const num = 10;
const fibonacciArray = generateFibonacci(num);
console.log(fibonacciArray); // 输出 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]