防抖函数
// 防抖函数
function debounce(fn, delay, immediate) {
let timer = null;
return function() {
const _this = this;
const args = [...argumets];
if (immediate && !timer) {
fn.apply(_this, args);
}
timer && clearTimeout(timer);
timer = setTimeout(_ => fn.apply(_this, args), delay);
}
}
截流函数
// 截流函数
function thtottle(fn, delay) {
let start = Date.now();
let timer = null;
return funciton() {
const _this = this;
const args = [...argumets];
let current = Date.now();
let remain = delay - (current - start);
timer && clearTimeout(timer);
if (remain <= 0) {
fn.apply(_this, args);
start = Date.now();
} else {
setTimeout(_ => fn.apply(_this, args), remain)
}
}
}
对象深拷贝
// 对象深拷贝
function deepClone(obj) {
let result;
if (Array.isArray(obj)) {
result = [];
} else if (obj && typeof obj === 'object') {
result = {};
} else {
return obj;
}
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
result[key] = deepClone(obj[key])
}
}
return result;
}
模拟promise
// 模拟promise
class MockPromise {
constructor(fn) {
this.state = pending;
this.value = undefined;
this.reason = undefined;
const resolve = value => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
}
};
const reject = value => {
if (this.state === 'pending') {
this.state = 'rejected'
this.reason = value
}
};
try {
fn(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onResolve, onReject) {
switch (this.state) {
case 'fulfilled':
onFulfilled();
break;
case 'rejected':
onRejected();
break;
default:
}
}
}
模拟create
// 模拟create
function mockCreate(obj) {
Function F() {};
F.prototype = obj;
return new F();
}
模拟call实现
// 模拟call实现
if (!Function.prototype.call) {
Function.prototype.call = function(context) {
if (typeof this !== 'function') {
// throw new Error('must function');
}
context = context || window;
const args = arguments.slice(1);
context.fn = this;
const result = context.fn(...args);
delete context.fn;
return result;
}
}
模拟apply实现
// 模拟apply实现
if (!Function.prototype.apply) {
Function.prototype.apply = function(context) {
if (typeof this !== 'function') {
// throw new Error('must function');
}
context = context || window;
context.fn = this;
const args = arguments.slice(1);
const result = context.fn(...args);
delete context.fn;
return result;
}
}
模拟bind实现
// 模拟bind实现
if(!Function.prototype.bind){
Function.prototype.bind = function(context){
// 首先判断this是不是function
if(typeof this !== 'function'){
// 抛出错误
}
var _this = this,
fNOP = function(){}, // 用于后面维护原型关系
args = Array.prototype.slice.call(arguments, 1), // 取出bind收到的参数,除去第一个作为上下文的参数并保存
fBound = function(){
_this.call(context, args.concat(Array.prototype.slice.call(arguments))) // 将bind接收的的参数和实际接收到的参数相连接
};
// 维护原型关系
if(this.prototype){
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
}
return fBound;
}
}
模拟new操作
// 模拟new操作
function mockNew () {
const newObj = {}
const _constructor = Array.prototype.shift.apply(arguments)
newObj.__proto__ = _constructor.prototype
_constructor.apply(newObj, arguments)
return newObj
}
模拟instanceOf操作
// 模拟instanceOf操作
function mockInstanceOf (L, R) {
//L 表示左表达式,R 表示右表达式
const o = R.prototype
let L = L.__proto__
while (true) {
if (L === null) return false
if (L === o) return true
L = L.__proto__
}
}
顺序查找
// 顺序查找
function sequentialSearch(item, arr) {
for (let i = 0, len = arr.length; i < len; i++) {
if (arr[i] === item) return i;
}
return -1;
}
二分查找
// 二分查找
function binarySearch(item, arr) {
arr.sort((a, b) => a - b);
let low = 0,
height = arr.length - 1;
while(low <= height) {
let mid = Math.floor(height - (height - low) / 2),
element = arr[mid];
if (item > element) {
low = mid + 1;
} else if (item < element) {
height < mid - 1;
} else {
return mid;
}
}
return -1;
}
冒泡排序
// 冒泡排序
function advanceBubbleSort(arr) {
for (let i = 1, len = arr.length; i < len; i++) {
for (let j = 0; j < len - i; j++) {
if (arr[j] > a[j + 1]) {
const temp = a[j + 1];
a[j + 1] = a[j];
a[j] = temp;
}
}
}
return arr;
}
选择排序
// 选择排序
function selectionSort(arr) {
for (let i = 0, len = arr.length; i < len; i++) {
let minIndex = i;
for (let j = i + 1; j < len; j++) {
if (arr[j] < arr[minIndex]) minIndex = j;
}
const temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
return arr;
}
插入排序
// 插入排序
function InsertionSort(arr){
for (let i = 0, len = arr.length; i < len; i++) {
let cur = arr[i];
let j = i;
while(j > 0 && arr[j - 1] > cur) {
arr[j] = arr[j - 1];
j--;
}
arr[j] = cur;
}
return arr;
}
快速排序
// 快速排序
function quickSort(arr) {
const left = [],
right = [],
pivotIndex = Math.floor(arr.length / 2),
pivot = arr.splice(pivotIndex, 1);
arr.forEach(val => {
if (val < pivot) {
left.push(val);
}
if (val > pivot) {
right.push(val);
}
})
return quickSort(left).concat([pivot], quickSort(right));
}
从一个数组中找出 N 个数,其和为 M 的所有可能
// 从一个数组中找出 N 个数,其和为 M 的所有可能
const n = (num) => {
return num.toString(2).replace(/0/g, '').length
}
const n = num => {
let count = 0
while(num) {
num &= (num - 1)
count++
}
return count
}
function search(arr, count, num) {
const result = [];
for (let i = 1; i < 1 << arr.length; i++) {
const s = 0, temp = [];
if (n(i) === count) {
for (let j = 0; j < arr.length; j++) {
if (i & (1 << j) !== 0) {
s += arr[j]; temp.push(arr[j]);
}
}
}
if (s === sum) {
result.push(temp);
}
}
return result;
}
JS字符串全排列
// JS字符串全排列
function permutate(str, result = []) {
const tempArr = [];
if (str.length === 0) return result;
if (result.length === 0) {
tempArr.push(str[0]);
} else {
for (let i = 0; i < result.length; i++) {
let item = result[i];
let itemLen = item.length;
for (j = 0; j < itemLen + 1; j++) {
tempArr.push(item.slice(0, j) + str[0] + item.slice(j))
}
}
}
return permutate(str.slice(1), tempArr);
}
链表反转
// 链表反转
function reverseList(head) {
if (head === null || head.next === null) {
return head;
} else {
let next = null;
let pre = null;
while(head) {
next = head.next;
head.next = pre;
pre = head;
head = next;
}
}
}
URL格式化
query格式化使用URLSearchParams

URL格式化使用URL

对象转换
let input = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
let output = {
'a.b.c.dd': 'abcdd',
'a.d.xx': 'adxx',
'a.e': 'ae'
}
// input => output
const isObj = obj => obj && typeof obj === 'object'
function flatObj (obj, parentKey = '', res = {}) {
if (!isObj(obj)) return
for (const [key, val] of Object.entries(obj)) {
const curentKey = parentKey ? `${parentKey}.${key}` : key
isObj(val) ? flatObj(val, curentKey, res) : res[curentKey] = val
}
return res
}
// output => input
function setObj (res, keyArr, val) {
let subObj = {}
if (!res[keyArr[0]]) res[keyArr[0]] = {}
subObj = res[keyArr[0]]
for (let i = 1; i < keyArr.length; i++) {
const val = keyArr[i]
if (!subObj[val]) subObj[val] = i === keyArr.length - 1 ? val : {}
subObj = subObj[val]
}
}
function mapObj (obj, res = {}) {
if (!isObj) return
for (const [key, val] of Object.entries(obj)) {
const keyArr = key.split('.')
setObj(res, keyArr, val)
}
return res
}
数组去重
1. 如传入的数组元素为[123, "meili", "123", "mogu", 123],则输出:[123, "meili", "123", "mogu"]
2. 如传入的数组元素为[123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"],则输出:[123, [1, 2, 3], [1, "2", 3], "meili"]
3. 如传入的数组元素为[123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"],则输出:[123, {a: 1}, {a: {b: 1}}, {a: "1"}, "meili"]
// 实现
const isObj = obj => obj && typeof obj === 'object'
const arrFlat = arr => {
if (!Array.isArray(arr)) return
const arrFormat = []
const arrRes = []
arr.forEach(val => {
const valFormat = isObj(val) ? JSON.stringify(val) : val
arrFormat.includes(valFormat) ? console.log('continue') : (arrRes.push(val) && arrFormat.push(valFormat))
})
return arrRes
}
找出字符串中连续出现最多的字符和个数
'abcaakjbb' => {'a':2,'b':2}
'abbkejsbcccwqaa' => {'c':3}
// 实现
const countChat = str => {
const matchStr = str.match(/(\w)\1*/g)
const max = Math.max(...matchStr.map(val => val.length))
return matchStr.reduce((pre, curent, index) => {
if (matchStr[index].length === max) pre[matchStr[index]] = matchStr[index].length
return pre
}, {})
}
实现~功能
输入 '1, 2, 3, 5, 7, 8, 10' 输出 '1~3, 5, 7~8, 10'
// 实现
const transformStr = str => {
const res = []
const arrStr = str.split(',').map(val => Number(val.trim())).sort((a, b) => a - b)
let flag = arrStr[0]
arrStr.reduce((pre, current, index) => {
if (current !== arrStr[index + 1] - 1) {
if (flag === current) {
pre.push(current)
} else {
pre.push(`${flag}~${current}`)
}
flag = arrStr[index + 1]
}
return pre.join(',')
}, res)
return res
}
深度遍历&&广度遍历
// 深度遍历
function dfs (node, nodeList = []) {
if (node) {
nodeList.push(node)
const children = [...node.children]
children.forEach(val => {
dfs(val, nodeList)
})
}
return nodeList
}
console.log('dfs:', dfs(document.body))
// 广度遍历
function bfs (node, nodeList = []) {
const stacks = []
if (node) {
stacks.push(node)
while (stacks.length) {
const item = stacks.pop()
const children = [...item.children]
nodeList.push(item)
children.forEach(val => stacks.push(val))
}
}
return nodeList
}
console.log('bfs:', bfs(document.body))
长整数相加
function bigNumSum (num1, num2, decimal = 10) {
const max = Math.max(num1.length, num2.length)
num1 = num1.padStart(max, '0')
num2 = num2.padStart(max, '0')
let res = ''
let anotherAdd = 0
for (let i = max - 1; i >= 0; i--) {
res = `${(parseInt(num1[i]) + parseInt(num2[i]) + anotherAdd) % decimal}${res}`
anotherAdd = Math.floor((Number(num1[i]) + Number(num2[i]) + anotherAdd) / decimal)
}
return anotherAdd ? `1${res}` : res
}
排序二叉树
class Node {
constructor (key) {
this.key = key
this.left = null
this.right = null
}
}
class BinaryTree {
constructor () {
this.root = null
}
insert (key) {
const newNode = new Node(key)
if (this.root) {
this.insertNode(newNode, this.root)
} else {
this.root = newNode
}
}
insertNode (node, root) {
if (node.key > root.key) {
root.right ? this.insertNode(node, root.right) : root.right = node
} else {
root.left ? this.insertNode(node, root.left) : root.left = node
}
}
inOrderTraverse (cb) {
this.inOrderTraverseNode(this.root, cb)
}
inOrderTraverseNode (root, cb) {
if (root) {
this.inOrderTraverseNode(root.left, cb)
cb(root.key)
this.inOrderTraverseNode(root.right, cb)
}
}
preOrderTraverse (cb) {
this.preOrderTraverseNode(this.root, cb)
}
preOrderTraverseNode (root, cb) {
if (root) {
cb(root.key)
this.preOrderTraverseNode(root.left, cb)
this.preOrderTraverseNode(root.right, cb)
}
}
postOrderTraverse (cb) {
this.postOrderTraverseNode(this.root, cb)
}
postOrderTraverseNode (root, cb) {
if (root) {
this.postOrderTraverseNode(root.left, cb)
this.postOrderTraverseNode(root.right, cb)
cb(root.key)
}
}
min () {
return this.minNode(this.root)
}
minNode (node) {
if (node) {
while (node && node.left) {
node = node.left
}
return node.key
}
return null
}
max () {
return this.maxNode(this.root)
}
maxNode (node) {
if (node) {
while (node && node.right) {
node = node.right
}
return node.key
}
return null
}
search (key) {
return this.searchNode(this.root, key)
}
searchNode (node, key) {
if (node) {
if (node.key < key) {
return this.searchNode(node.right, key)
} else if (node.key > key) {
return this.searchNode(node.left, key)
} else {
return true
}
}
return false
}
remove (key) {
this.removeNode(this.root, key)
return this.root
}
findMinNode (node) {
if (node) {
while (node && node.left) {
node = node.left
}
return node
}
return null
}
removeNode (node, key) {
if (node === null) return null
if (key < node.key) {
node.left = this.removeNode(node.left, key)
return node
} else if (key > node.key) {
node.right = this.removeNode(node.right, key)
return node
} else {
if (node.left === null && node.right === null) {
node = null
return node
}
if (node.left === null) {
node = node.right
return node
} else if (node.right === null) {
node = node.left
return node
} else {
const minNode = this.findMinNode(node.right)
node.key = minNode.key
node.right = this.removeNode(node.right, minNode.key)
return node
}
}
}
}
约瑟夫问题
function countOff (N, M) {
if (N < 1 || M < 1) {
return
}
const source = Array(...Array(N)).map((_, i) => i + 1)
let index = 0
while (source.length > 1) {
index = (index + M - 1) % source.length
source.splice(index, 1)
}
return source[0]
}