一、永恒的经典
const arr = [1, 8, 2, 1, 0, 6];
const 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]];
}
}
}
for (let i = 1; i < N; i++) {
let j;
let key = arr[i];
for (j = i - 1; j >= 0 && arr[j] > key; j--) {
arr[j + 1] = arr[j];
}
arr[j + 1] = key;
}
for (let i = 0; i < N - 1; i++) {
let minIndex = i;
for (let j = i + 1; j < N; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
if (minIndex != i) {
[arr[minIndex], arr[i]] = [arr[i], arr[minIndex]];
}
}
function mergeSort(arr) {
if (arr.length <= 1) return arr;
const mid = Math.floor(arr.length / 2);
const left = mergeSort(arr.slice(0, mid));
const right = mergeSort(arr.slice(mid));
return merge(left, right);
}
function merge(left, right) {
let result = [];
let i = 0;
let j = 0;
while (i < left.length && j < right.length) {
if (left[i] < right[j]) {
result.push(left[i++]);
} else {
result.push(right[j++]);
}
}
return result.concat(left.slice(i)).concat(right.slice(j));
}
function quickSort(arr, low = 0, high = arr.length - 1) {
if (low < high) {
const pivotIndex = partition(arr, low, high);
quickSort(arr, low, pivotIndex - 1);
quickSort(arr, pivotIndex + 1, high);
}
return arr;
}
function partition(arr, low, high) {
const pivot = arr[high];
let i = low - 1;
for (let j = low; j < high; j++) {
if (arr[j] <= pivot) {
i++;
[arr[i], arr[j]] = [arr[j], arr[i]];
}
}
[arr[i + 1], arr[high]] = [arr[high], arr[i + 1]];
return i + 1;
}
const arr = [38, 27, 43, 3, 9, 82, 10];
console.log(quickSort(arr));
function heapSort(arr) {
const n = arr.length;
for (let i = Math.floor(n / 2) - 1; i >= 0; i--) {
heapify(arr, n, i);
}
for (let i = n - 1; i > 0; i--) {
[arr[0], arr[i]] = [arr[i], arr[0]];
heapify(arr, i, 0);
}
return arr;
}
function heapify(arr, n, i) {
let largest = i;
const left = 2 * i + 1;
const right = 2 * i + 2;
if (left < n && arr[left] > arr[largest]) {
largest = left;
}
if (right < n && arr[right] > arr[largest]) {
largest = right;
}
if (largest !== i) {
[arr[i], arr[largest]] = [arr[largest], arr[i]];
heapify(arr, n, largest);
}
}
const arr = [38, 27, 43, 3, 9, 82, 10];
console.log(heapSort(arr));
二、节流、防抖与柯里化
function throttle(fn, interval) {
let callTime = 0;
return function (...args) {
const now = Date.now();
if (now - callTime >= interval) {
fn.apply(this, args);
callTime = now;
}
};
}
function debounce(fn, delay) {
let timer = 0;
return function (...args) {
timer && clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}
function curry(fn) {
const arity = fn.length;
function curried(...args) {
if (args.length >= arity) {
return fn(...args);
} else {
return function (...moreArgs) {
return curried(...args, ...moreArgs);
};
}
}
return curried;
}
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
} else {
return function (...moreArgs) {
return curried.apply(this, args.concat(moreArgs));
};
}
};
}
const add = curry((a, b, c) => a + b + c);
console.log(add(1)(2)(3));
console.log(add(1, 2)(3));
三、普通函数与箭头函数的this
function outer() {
if (true) {
const arrowFunc = () => {
console.log("箭头~", this);
};
arrowFunc();
const regularFunc = function () {
console.log("普通~", this);
};
regularFunc();
}
}
outer.call({
name: "Charlie",
});
outer();
const obj = {
name: "Bob",
regularMethod: function () {
const arrowFunc = () => {
console.log("箭头~", this);
};
arrowFunc();
const regularFunc = function () {
console.log("普通~", this);
};
regularFunc();
},
};
obj.regularMethod();
四、易混淆知识点
Array Array.of Array.from
splice slice substring substr
五、经典笔试题
1、发布订阅模式
class EventEmitter {
constructor() {
this.events = [];
}
on(event, cb) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(cb);
}
emit(event, ...args) {
if (this.events[event]) {
this.events[event].forEach((cb) => {
cb(...args);
});
}
}
off(event, cb) {
if (this.events[event]) {
this.events[event] = this.events[event].filter(
(callback) => callback !== cb,
);
}
}
}
const emitter = new EventEmitter();
emitter.on("msg", (msg) => {
console.log(`hi,${msg}`);
});
emitter.emit("msg", "999");
2、并发控制
async function runTasks(tasks, concurrency) {
const results = [];
const runningTasks = new Set();
for (let i = 0; i < tasks.length; i++) {
const taskPromise = tasks[i]().then((res) => {
runningTasks.delete(taskPromise);
results[i] = res;
});
runningTasks.add(taskPromise);
if (runningTasks.size >= concurrency) {
await Promise.race(runningTasks);
}
}
await Promise.all(runningTasks);
return results;
}
const tasks = [
() =>
new Promise((resolve) =>
setTimeout(() => {
resolve("Task 1");
}, 1000),
),
() =>
new Promise((resolve) =>
setTimeout(() => {
resolve("Task 2");
}, 500),
),
() =>
new Promise((resolve) =>
setTimeout(() => {
resolve("Task 3");
}, 2000),
),
];
runTasks(tasks, 2).then((res) => {
console.log(res);
});
3、爬楼梯
function climbStairs(n) {
if (n <= 2) return n;
let prev1 = 1;
let prev2 = 2;
for (let i = 3; i <= n; i++) {
const current = prev1 + prev2;
prev1 = prev2;
prev2 = current;
}
return prev2;
}
function climbStairs(n) {
if (n < 3) return n;
let prev1 = 1,
prev2 = 2;
while (n-- > 2) {
[prev1, prev2] = [prev2, prev1 + prev2];
}
return prev2;
}
4、有效回文串
function canMakePalindrome(s) {
let mismatch = 0;
for (let i = 0, j = s.length - 1; i < j; i++, j--) {
if (s[i] !== s[j] && ++mismatch > 2) return false;
}
return mismatch < 3;
}
5、深度克隆
function deepClone(obj, hash = new WeakMap()) {
if (obj === null || typeof obj !== "object") {
return obj;
}
if (hash.has(obj)) {
return hash.get(obj);
}
if (obj instanceof Date) {
const clone = new Date(obj);
hash.set(obj, clone);
return clone;
}
if (obj instanceof RegExp) {
const clone = new RegExp(obj);
hash.set(obj, clone);
return clone;
}
if (obj instanceof Map) {
const clone = new Map();
hash.set(obj, clone);
obj.forEach((value, key) => {
clone.set(deepClone(key, hash), deepClone(value, hash));
});
return clone;
}
if (obj instanceof Set) {
const clone = new Set();
hash.set(obj, clone);
obj.forEach((value) => {
clone.add(deepClone(value, hash));
});
return clone;
}
if (ArrayBuffer.isView(obj)) {
const clone = new obj.constructor(obj);
hash.set(obj, clone);
return clone;
}
if (obj instanceof ArrayBuffer) {
const clone = obj.slice(0);
hash.set(obj, clone);
return clone;
}
if (typeof obj === "function") {
return obj;
}
const clone = Object.create(Object.getPrototypeOf(obj));
hash.set(obj, clone);
const allKeys = Object.getOwnPropertyNames(obj).concat(
Object.getOwnPropertySymbols(obj),
);
for (const key of allKeys) {
const descriptor = Object.getOwnPropertyDescriptor(obj, key);
if (descriptor) {
if (typeof descriptor.value === "object" && descriptor.value !== null) {
descriptor.value = deepClone(descriptor.value, hash);
}
Object.defineProperty(clone, key, descriptor);
}
}
return clone;
}
6、sp通配符匹配
var isMatch = function (s, p) {
const m = s.length,
n = p.length;
const dp = Array.from({ length: m + 1 }).map(() =>
Array.from({ length: n + 1 }).map(() => false),
);
dp[0][0] = true;
for (let i = 1; i <= n; i++) {
dp[0][i] = dp[0][i - 1] && p[i - 1] == "*";
}
for (let i = 1; i <= m; i++) {
for (let j = 1; j <= n; j++) {
if (s[i - 1] == p[j - 1] || p[j - 1] == "?") {
dp[i][j] = dp[i - 1][j - 1];
} else if (p[j - 1] == "*") {
dp[i][j] = dp[i][j - 1] || dp[i - 1][j];
}
}
}
return dp[m][n];
};
六、正则经典
手机号验证(中国大陆)
/^1[3-9]\d{9}$/.test('13800138000')
邮箱验证
/^[\w-]+(.[\w-]+)*@[\w-]+(.[\w-]+)+$/.test('test@example.com')
身份证号验证(简单版)
/^\d{17}[\dXx]$/.test('11010119900307783X')
中文汉字匹配
/^[\u4e00-\u9fa5]+$/.test('中文测试')
提取域名
'https://example.com/path'.match(/https?:\/\/([^/]+)/)[1]
数字提取
'价格¥299'.match(/\d+/)[0]
日期格式验证(YYYY-MM-DD)
/^\d{4}-\d{2}-\d{2}$/.test('2025-09-28')
密码强度验证(6-12位字母数字)
/^[a-zA-Z0-9]{6,12}$/.test('Pass123')
HTML标签内容提取
'<div>content</div>'.match(/<[^>]+>([^<]+)</)[1]
空白字符替换
'多 个 空格'.replace(/\s+/g,'')
一百分、其他
面试方法论
1、慢一点&&被提问环节至少问对方至少5个问题
2、star法则 情景 目标 行动 结果
3、总分总
4、prep 观点 理由 举例子 总结
function getType(value) {
return Object.prototype.toString.call(value)
.match(/\s+(\w+)/)[1]
.toLowerCase();
}
闭包:函数能访问并记住其词法作用域,即使函数在作用域外执行。
前端性能优化
代码压缩(gzip、丑化、多目标打包)
图片懒加载(webp、雪碧图、base64)
HTTP(http2、多静态资源域)
缓存、CDN