1.防抖
const debounce = (fn, ms = 0) => {
let timer;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), ms);
};
};
2.节流
function throttle(func, delay) {
let lastTime = 0;
return function(...args) {
const currentTime = Date.now();
if (currentTime - lastTime >= delay) {
func.apply(this, args);
lastTime = currentTime;
}
}
}
3.实现 LazyMan
题目描述:
要求设计 LazyMan 类,实现以下功能。
LazyMan('Tony');
// Hi I am Tony
LazyMan('Tony').sleep(10).eat('lunch');
// Hi I am Tony
// 等待了10秒...
// I am eating lunch
LazyMan('Tony').eat('lunch').sleep(10).eat('dinner');
// Hi I am Tony
// I am eating lunch
// 等待了10秒...
// I am eating diner
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
// Hi I am Tony
// 等待了5秒...
// I am eating lunch
// I am eating dinner
// 等待了10秒...
// I am eating junk food
实现代码如下:
class LazyManClass {
constructor(name) {
this.name = name;
this.queue = [];
console.log(`Hi I am ${name}`);
setTimeout(() => {
this.next();
}, 0);
}
sleepFirst(time) {
const fn = () => {
setTimeout(() => {
console.log(`等待了${time}秒...`);
this.next();
}, time * 1000);
};
this.queue.unshift(fn);
return this;
}
sleep(time) {
const fn = () => {
setTimeout(() => {
console.log(`等待了${time}秒...`);
this.next();
}, time * 1000);
};
this.queue.push(fn);
return this;
}
eat(food) {
const fn = () => {
console.log(`I am eating ${food}`);
this.next();
};
this.queue.push(fn);
return this;
}
next() {
const fn = this.queue.shift();
fn && fn();
}
}
function LazyMan(name) {
return new LazyManClass(name);
}
4.深克隆
function clone(target, map = new WeakMap()) {
if (typeof target === 'object') {
let cloneTarget = Array.isArray(target) ? [] : {};
if (map.get(target)) {
return target;
}
map.set(target, cloneTarget);
for (const key in target) {
cloneTarget[key] = clone(target[key], map);
}
return cloneTarget;
} else {
return target;
}
};
5.数组扁平化
function flatten(arr) {
return arr.reduce((prev, curr) => {
return prev.concat(Array.isArray(curr) ? flatten(curr) : curr);
}, []);
}
6.快速排序
const quickSort = arr => {
const a = [...arr];
if (a.length < 2) return a;
const pivotIndex = Math.floor(arr.length / 2);
const pivot = a[pivotIndex];
const [lo, hi] = a.reduce(
(acc, val, i) => {
if (val < pivot || (val === pivot && i != pivotIndex)) {
acc[0].push(val);
} else if (val > pivot) {
acc[1].push(val);
}
return acc;
},
[[], []]
);
return [...quickSort(lo), pivot, ...quickSort(hi)];
};
// Examples
quickSort([1, 6, 1, 5, 3, 2, 1, 4]); // [1, 1, 1, 2, 3, 4, 5, 6]
7.冒泡排序
const bubbleSort = (arr) => {
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
[a[j], a[j + 1]] = [a[j + 1], a[j]];
}
}
}
};
8.归并排序
const mergeSort = arr => {
if (arr.length < 2) return arr;
const mid = Math.floor(arr.length / 2);
const l = mergeSort(arr.slice(0, mid));
const r = mergeSort(arr.slice(mid, arr.length));
return Array.from({ length: l.length + r.length }, () => {
if (!l.length) return r.shift();
else if (!r.length) return l.shift();
else return l[0] > r[0] ? r.shift() : l.shift();
});
};
// Examples
mergeSort([5, 1, 4, 2, 3]); // [1, 2, 3, 4, 5]
9.插入排序
const insertionSort = arr =>
arr.reduce((acc, x) => {
if (!acc.length) return [x];
acc.some((y, j) => {
if (x <= y) {
acc.splice(j, 0, x);
return true;
}
if (x > y && j === acc.length - 1) {
acc.splice(j + 1, 0, x);
return true;
}
return false;
});
return acc;
}, []);
// Examples
insertionSort([6, 3, 4, 1]); // [1, 3, 4, 6]
10.选择排序
const selectionSort = arr => {
const a = [...arr];
for (let i = 0; i < a.length; i++) {
const min = a
.slice(i + 1)
.reduce((acc, val, j) => (val < a[acc] ? j + i + 1 : acc), i);
if (min !== i) [a[i], a[min]] = [a[min], a[i]];
}
return a;
};
// Examples
selectionSort([5, 1, 4, 2, 3]); // [1, 2, 3, 4, 5]
11.实现new
function myNew(fn, ...args) {
let obj = Object.create(fn.prototype);
let res = fn.call(obj, ...args);
if (res && (typeof res === "object" || typeof res === "function")) {
return res;
}
return obj;
}
12.二分查找
const binarySearch = (arr, item) => {
let l = 0,
r = arr.length - 1;
while (l <= r) {
const mid = Math.floor((l + r) / 2);
const guess = arr[mid];
if (guess === item) return mid;
if (guess > item) r = mid - 1;
else l = mid + 1;
}
return -1;
};
13.寄生组合继承
function Parent(name) {
this.name = name;
this.say = () => {
console.log(111);
};
}
function Children(name) {
Parent.call(this);
this.name = name;
}
Children.prototype = Object.create(Parent.prototype);
Children.prototype.constructor = Children;
14.函数柯里化
const curry = (fn, ...args) =>
args.length >= fn.length
? fn(...args)
: (..._args) => curry(fn, ...args, ..._args);
function add1(x, y, z) {
return x + y + z;
}
const add = curry(add1);
console.log(add(1, 2, 3));
console.log(add(1)(2)(3));
console.log(add(1, 2)(3));
console.log(add(1)(2, 3));
15.发布订阅模式
class EventEmitter {
constructor() {
this.events = {}; // 用一个对象来保存事件和订阅者
}
// 添加事件
on(event, listener) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(listener);
}
// 触发事件
emit(event, ...args) {
const listeners = this.events[event] || [];
listeners.forEach((listener) => listener(...args));
}
// 移除事件
off(event, listener) {
const listeners = this.events[event] || [];
const index = listeners.indexOf(listener);
if (index >= 0) {
listeners.splice(index, 1);
}
}
}
调用示例:
const emitter = new EventEmitter();
// 添加订阅者
emitter.on('hello', (name) => {
console.log(`Hello, ${name}!`);
});
// 触发事件
emitter.emit('hello', 'Tom'); // 输出:Hello, Tom!
16.列表转成树形结构
题目描述:
[
{
id: 1,
text: '节点1',
parentId: 0 //这里用0表示为顶级节点
},
{
id: 2,
text: '节点1_1',
parentId: 1 //通过这个字段来确定子父级
}
...
]
转成
[
{
id: 1,
text: '节点1',
parentId: 0,
children: [
{
id:2,
text: '节点1_1',
parentId:1
}
]
}
]
实现代码如下:
function listToTree(data) {
let temp = {};
let treeData = [];
for (let i = 0; i < data.length; i++) {
temp[data[i].id] = data[i];
}
for (let i in temp) {
if (+temp[i].parentId != 0) {
if (!temp[temp[i].parentId].children) {
temp[temp[i].parentId].children = [];
}
temp[temp[i].parentId].children.push(temp[i]);
} else {
treeData.push(temp[i]);
}
}
return treeData;
}
17.实现instanceof
function myInstanceof(target, origin) {
const proto = target.__proto__;
if (proto) {
if (origin.prototype === proto) {
return true;
} else {
return myInstanceof(proto, origin)
}
} else {
return false;
}
}
18.promise
class MyPromise {
constructor(executor) {
this.state = 'pending';
this.value = null;
this.reason = null;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.onResolvedCallbacks.forEach(callback => callback(value));
}
}
const reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach(callback => callback(reason));
}
}
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onResolved, onRejected) {
onResolved = typeof onResolved === 'function' ? onResolved : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
const promise = new MyPromise((resolve, reject) => {
const handle = (callback, state) => {
try {
const result = callback(this.value);
if (result instanceof MyPromise) {
result.then(resolve, reject);
} else {
state(result);
}
} catch (error) {
reject(error);
}
}
if (this.state === 'fulfilled') {
setTimeout(() => handle(onResolved, resolve), 0);
} else if (this.state === 'rejected') {
setTimeout(() => handle(onRejected, reject), 0);
} else {
this.onResolvedCallbacks.push(() => handle(onResolved, resolve));
this.onRejectedCallbacks.push(() => handle(onRejected, reject));
}
});
return promise;
}
catch(onRejected) {
return this.then(null, onRejected);
}
static resolve(value) {
return new MyPromise(resolve => resolve(value));
}
static reject(reason) {
return new MyPromise((_, reject) => reject(reason));
}
static all(promises) {
return new MyPromise((resolve, reject) => {
const results = [];
let count = 0;
const handleResult = (index, value) => {
results[index] = value;
count++;
if (count === promises.length) {
resolve(results);
}
}
for (let i = 0; i < promises.length; i++) {
promises[i].then(value => handleResult(i, value), reject);
}
});
}
static race(promises) {
return new MyPromise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then(resolve, reject);
}
});
}
}
19.实现斐波那契数列
const fib = n => {
let dp = [0, 1]
for(let i = 2; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2]
}
return dp[n]
};
20.实现compose函数
function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg
}
if (funcs.length === 1) {
return funcs[0]
}
return funcs.reduce((a, b) => (...args) => a(b(...args)))
}
21.实现一个 sleep 睡眠函数
const sleep = time => {
return new Promise(resolve => {
setTimeout(resolve, time);
});
};
sleep(2000).then(() => {
console.log(111);
});
22.递归合并对象函数
function isObject (value) {
const type = typeof value
return value !== null && (type === 'object' || type === 'function')
}
// { a: [{ b: 2 }] } { a: [{ c: 2 }]} -> { a: [{b:2}, {c:2}]}
// merge({o: {a: 3}}, {o: {b:4}}) => {o: {a:3, b:4}}
function merge (source, other) {
if (!isObject(source) || !isObject(other)) {
return other === undefined ? source : other
}
// 合并两个对象的 key,另外要区分数组的初始值为 []
return Object.keys({
...source,
...other
}).reduce((acc, key) => {
// 递归合并 value
acc[key] = merge(source[key], other[key])
return acc
}, Array.isArray(source) ? [] : {})
}
23.树结构转列表结构
function treeToList (tree, result = [], level = 0) {
tree.forEach(node => {
result.push(node)
node.level = level + 1
node.children && treeToList(node.children, result, level + 1)
})
return result
}