防抖
<body>
<button class="btn">发请求</button>
<script>
const btn = document.querySelector('.btn')
function handle() {
console.log('向后端发请求');
}
btn.addEventListener('click', debounce(handle, 1000))
function debounce(fn, wait) {
let timer = null
return function (...args) {
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
fn.call(this, ...args)
}, wait)
}
}
</script>
</body>
节流
<body>
<button class="btn">发请求</button>
<script>
const btn = document.querySelector('.btn')
function handle() {
console.log('向后端发请求');
}
btn.addEventListener('click', throttle(handle, 1000))
function throttle(fn, wait) {
let preTime = null
return function (...args) {
let nowTime = Date.now()
if (nowTime - preTime >= wait) {
fn.call(this, ...args)
preTime = nowTime
}
}
}
</script>
</body>
call,apply,bind
// call 将一个函数强行绑定到一个对象身上
function foo(x) {
console.log(this.a, x);
}
const obj = {
a: 1
}
foo.call(obj, 3) // 1 3
Function.prototype.myCall = function (...args) {
const context = args[0]
const arg = args.splice(1)
context.fn = this
const res = context.fn(...arg)
delete context.fn
return res
}
foo.myCall(obj, 3)
// apply 以数组形式接收参数
function foo(x, y) {
console.log(this.a, x, y);
}
const obj = {
a: 1
}
foo.apply(obj, [2, 3]) // 1 2 3
Function.prototype.myApply = function (obj, args) {
const context = obj
context.fn = this
const res = context.fn(...args)
delete context.fn
return res
}
foo.myApply(obj, [2, 3]) // 1 2 3
// bind 内部返回一个函数
function foo(x, y) {
console.log(this.a, x, y);
}
const obj = {
a: 1
}
const res = foo.bind(obj, 2)
res(3) // 1 2 3
Function.prototype.myBind = function (context, ...args) {
if (typeof this !== 'function') {
throw new TypeError("Error")
}
const fn = this
return function Fn(...arg) {
const arr = args.concat(arg)
fn.apply(context, arr)
}
}
const res1 = foo.myBind(obj, 2)
res1(3) // 1 2 3
new 实现
Person.prototype.sayName = function () {
console.log(this.name);
}
function Person(name, age) {
this.name = name
this.age = 18
// return [] 如果这个是引用类型就输出这个,反之输出原来的
}
let p = new Person('张三', 18)
console.log(p); // Person { name: '张三', age: 18 }
p.sayName(); // 张三
// myNew 实现
function myNew(constructor, ...args) {
let obj = {}
// obj.__proto__ = constructor.prototype
obj = Object.create(constructor.prototype)
const result = constructor.apply(obj, args)
return result instanceof Object ? result : obj
}
let p = myNew(Person, '张三', 18)
console.log(p); // Person { name: '张三', age: 18 }
p.sayName(); // 张三
instanceof
// instanceof 是用来判断一个对象是否是一个类的实例
function Car() {
this.run = 'running'
}
Bus.prototype = new Car()
function Bus() {
this.name = 'su7'
}
let bus = new Bus()
console.log(bus instanceof Bus); // true
console.log(bus instanceof Car); // true
console.log(bus instanceof Object); // true
console.log([1, 2, 3] instanceof Array); // true
console.log([1, 2, 3] instanceof Object); //true
function myinstanceof(L, R) {
while (L !== null) {
L = L.__proto__
if (L === R.prototype) {
return true
}
}
return false
}
console.log(myinstanceof([1, 2, 3], Array)); // true
console.log(myinstanceof([1, 2, 3], Object)); // true
console.log(myinstanceof({ a: 1 }, Array)); // false
浅拷贝
常见方法:Object.assign({},obj),[].concat(arr),数组解构,arr.slice()等。
Object.prototype.say = 'hello'
const obj = {
name: '张三',
age: 18,
like: {
n: 'running'
}
}
function shallow(obj) {
let res = {}
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
res[key] = obj[key]
}
}
return res
}
console.log(shallow(obj)); // { name: '张三', age: 18, like: { n: 'running' } }
深拷贝
常见方法:JSON.parse(JSON.stringify(obj)),structuredClone(obj)
Object.prototype.say = 'hello'
const obj = {
name: '张三',
age: 18,
like: {
n: 'running'
}
}
function deepClone(obj) {
let res = obj instanceof Array ? [] : {}
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
if (typeof obj[key] === 'object' && typeof obj[key] !== null) {
res[key] = deepClone(obj[key])
} else {
res[key] = obj[key]
}
}
}
return res
}
let newObj = deepClone(obj)
newObj.like.n = 'say'
console.log(newObj); // { name: '张三', age: 18, like: { n: 'say' } }
数组去重
常见方法:双重for循环,for+indexOf,for+includes
// filter + sort
// 先排序再拿该值与前一个值比较,return 出改值与前面一个值不相等的值
const arr = [1, 2, 3, 4, 1, 2]
function unique(arr) {
let newArr = arr
let res = newArr.sort().filter((item, index, arr) => {
return index === 0 || item !== arr[index - 1]
})
return res
}
console.log(unique(arr)); // [ 1, 2, 3, 4 ]
// 存入一个对象中
const arr = [1, 2, 3, 4, 1, 2]
// 若已有该值为true
// {
// 1:true,
// 2:true
// }
function unique(arr) {
let obj = {}
for (let i = 0; i < arr.length; i++) {
if (!obj[arr[i]]) {
obj[arr[i]] = true
}
}
return Object.keys(obj).map(Number)
}
console.log(unique(arr)); // [ 1, 2, 3, 4 ]
// Set 数据结构
let s = new Set()
s.add(1)
s.add(2)
s.add(1)
console.log(s); // Set(2) { 1, 2 }
console.log(...s); // 1 2
// 去重实现
const arr = [1, 2, 3, 4, 1, 2]
function unique(arr) {
let res = new Set(arr)
return [...res]
}
console.log(unique(arr)); //[ 1, 2, 3, 4 ]
map遍历
// 数组遍历,接收三个参数,返回符合条件的参数
const arr = [1, 2, 3, 4, 5, 6]
// let res = arr.map((item, index, arr) => {
// return item * 2
// })
// console.log(res); // [ 2, 4, 6, 8, 10, 12 ]
Array.prototype.myMap = function (callback) {
let res = []
for (let i = 0; i < this.length; i++) {
res.push(callback(this[i], i, this))
}
return res
}
let res = arr.myMap((item, index, arr) => {
return item * 2
})
console.log(res);
for...of
// for...of 是遍历有迭代器属性的对象
function forOf(obj, cb) {
if (!obj[Symbol.iterator]) {
throw new TypeError(obj + "is not iterator")
}
let iterator = obj[Symbol.iterator]()
let res = iterator.next()
while (!res.done) {
cb(res.value)
res = iterator.next()
}
}
let arr = [1, 2, 3, 4]
forOf(arr, function (value) {
console.log(value);
})
扁平化
数组扁平化:
let arr = [1, [2, [3, 4]]]
// console.log(arr.flat(Infinity)); // [ 1, 2, 3, 4 ]
function flatten(arr) {
let result = []
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
// result = result.concat(flatten(item))
// result.push(...flatten(item))
result = [...result, ...flatten(item)]
} else {
res.push(arr[i])
}
}
return result
}
console.log(flatten(arr));
// concat 拼接数组时,会去掉一层[]
function flatten(arr) {
while (arr.some(item => Array.isArray(item))) { // 只要有一个满足条件就返回true
arr = [].concat(...arr)
}
return arr
}
console.log(flatten(arr)); // [ 1, 2, 3, 4 ]
对象扁平化:
// 对象的扁平化
const obj = {
a: 1,
b: [1, 2, { c: 3 }, [4]],
d: {
e: 2,
f: 3
}
}
// {
// a: 1,
// 'b[0]': 1,
// 'b[1]': 2,
// 'b[2].c': 3,
// 'b[3][0]': 4,
// 'd.e': 2,
// 'd.f': 3
// }
function flatObj(obj) {
let res = {}
function help(obj, oldKey) {
for (let key in obj) {
let newKey
if (oldKey) {
if (Array.isArray(oldKey)) {
newKey = `${oldKey}[${key}]`
} else {
newKey = `${oldKey}.${key}`
}
} else {
newKey = key
}
if (Object.prototype.toString.call(obj[key]) === '[object Object]' || Array.isArray(obj[key])) {
help(obj[key], newKey)
} else {
res[newKey] = obj[key]
}
}
}
help(obj, '')
return res
}
console.log(flatObj(obj));
快排
const arr = [1, 5, 2, 1, 4, 9, 6]
function quickSort(arr) {
if (arr.length <= 1) {
return arr
}
let left = []
let right = []
let middleIndex = Math.floor((arr.length / 2))
let middle = arr.splice(middleIndex, 1)[0]
for (let i = 0; i < arr.length; i++) {
if (arr[i] <= middle) {
left.push(arr[i])
} else {
right.push(arr[i])
}
}
return [...quickSort(left), middle, ...quickSort(right)]
}
console.log(quickSort(arr));
归并排序
const arr = [1, 5, 2, 1, 4, 9, 6]
function mergeSort(arr) {
const len = arr.length
if (len <= 1) {
return arr
}
let mid = Math.floor(len / 2)
const leftArr = mergeSort(arr.slice(0, mid))
const rightArr = mergeSort(arr.slice(mid))
arr = merge(leftArr, rightArr)
return arr
}
function merge(arr1, arr2) {
let res = []
let i = 0, j = 0
let len1 = arr1.length, len2 = arr2.length
while (i < len1 && j < len2) {
if (arr1[i] < arr2[j]) {
res.push(arr1[i])
i++
} else {
res.push(arr2[j])
j++
}
}
if (i < len1) {
res = res.concat(arr1.slice(i))
} else {
res = res.concat(arr2.slice(j))
}
return res
}
console.log(mergeSort(arr));
斐波那契
function fib(n) {
if (n === 0 || n === 1) return 1
return fib(n - 1) + fib(n - 2)
}
function fibonacci(n) {
if (n <= 1) return n
let fib = [0, 1]
for (let i = 0; i < n; i++) {
fib[i] = fib[i - 1] + fib[i - 2] // 计算第 i 个斐波那契数列的结果
}
return fib[n]
}
如有哪些补充,欢迎在评论区留言分享