Coding
deepClone
js
function deepCopy(obj) {
if (typeof obj != 'object') {
return obj
}
let result = (obj instanceof Array) ? [] : {}
for (let key in obj) {
if (obj[key] instanceof Date) {
result[key] = new Date(obj[key].getTime())
} else if (obj[key] instanceof RegExp) {
result[key] = new RegExp(obj[key])
}
else {
result[key] = deepCopy(obj[key])
}
}
return result
}
const objA = {
name: 'jack',
birthday: new Date(),
pattern: /jack/g,
// body: document.body,
others: [123, 'coding', new Date(), /abc/gim,]
};
const objB = deepCopy(objA);
console.log(objB)
防抖函数
TIP
浏览器的 resize、scroll、keypress、mousemove 等事件在触发时,会不断地调用绑定在事件上的回调函数,极大地浪费资源,降低前端性能
为了优化体验,需要对这类事件进行调用次数的限制,对此我们就可以采用 防抖(debounce) 和 节流(throttle) 的方式来减少调用频率
防抖和节流区别
- 相同点: 都可以通过使用 setTimeout 实现,两者目的都是降低回调执行频率和节省计算资源。
- 不同点:
- 函数防抖,在一段连续操作结束后,处理回调,利用clearTimeout和 setTimeout实现。函数节流,在一段连续操作中,每一段时间只执行一次,频率较高的事件中使用来提高性能
- 函数防抖关注一定时间连续触发的事件,只在最后执行一次,而函数节流一段时间内只执行一次
js
function fangdou(fn, delay) {
let time = null;
return function () {
if (time) clearTimeout(time)
time = setTimeout(() => {
fn.apply(this, arguments)
console.log("???")
}, delay)
}
}
// test
function testDebounce(e, content) {
console.log(e, content);
}
var testDebounceFn = fangdou(testDebounce, 1000); // 防抖函数
document.onmousemove = function (e) {
testDebounceFn(e, 'debounce'); // 给防抖函数传参
}
节流函数
js
function jieliu(fn, delay) {
let time = 0;
return function () {
let now = Date.now()
let span = now - time
var args = arguments
if (span > delay) {
time = now
fn("!!!")
}
}
}
let testjieliu = jieliu(clicking, 1000)
window.onclick = function () {
testjieliu("!!!")
}
function clicking(a) {
console.log(a)
}
归并排序和快速排序
js
//归并排序
Array.prototype.mergeSort = function() {
const half = this.length / 2
if (this.length < 2) {
return this
}
const left = this.splice(0, half)
return merge(this.mergeSort(), left.mergeSort())
}
function merge(left, right) {
let arr = []
while (left.length && right.length) {
if (left[0] < right[0]) {
arr.push(left.shift())
} else {
arr.push(right.shift())
}
}
arr.push(...left, ...right)
return arr
}
console.log([3, 7, 2, 4, 6, 1, 5].mergeSort())
js
//快速排序
function quick_sort(arr, start, end) {
console.log(start, end)
if (start >= end) return
let left = start
let right = end
let pivot = arr[start]
while (left < right) {
console.log(left, right)
while (left < right && arr[right] > pivot) right -= 1
arr[left] = arr[right]
while (left < right && arr[left] <= pivot) left += 1
arr[right] = arr[left]
}
arr[left] = pivot
quick_sort(arr, start, left - 1)
quick_sort(arr, left + 1, end)
}
let arr = [4, 7, 2, 5, 8, 3, 6]
quick_sort(arr, 0, 6)
console.log(arr)
Promise all/allsettled/any/race
- Promise.all() 静态方法接受一个 Promise 可迭代对象作为输入,并返回一个 Promise。当所有输入的 Promise 都被兑现时,返回的 Promise 也将被兑现(即使传入的是一个空的可迭代对象),并返回一个包含所有兑现值的数组。如果输入的任何 Promise 被拒绝,则返回的 Promise 将被拒绝,并带有第一个被拒绝的原因。
- Promise.allSettled() 静态方法将一个 Promise 可迭代对象作为输入,并返回一个单独的 Promise。当所有输入的 Promise 都已敲定时(包括传入空的可迭代对象时),返回的 Promise 将被兑现,并带有描述每个 Promise 结果的对象数组。
- Promise.race() 静态方法接受一个 promise 可迭代对象作为输入,并返回一个 Promise。这个返回的 promise 会随着第一个 promise 的敲定而敲定。
- Promise.any() 静态方法将一个 Promise 可迭代对象作为输入,并返回一个 Promise。当输入的任何一个 Promise 兑现时,这个返回的 Promise 将会兑现,并返回第一个兑现的值。当所有输入 Promise 都被拒绝(包括传递了空的可迭代对象)时,它会以一个包含拒绝原因数组的 AggregateError 拒绝。
js
//promise.all
function getSth(delay) {
return new Promise((res, rej) => {
setTimeout(() => {
console.log("1")
res(delay)
}, delay)
})
}
function getSthFail(delay) {
return new Promise((res, rej) => {
setTimeout(() => {
console.log("1")
rej(delay)
}, delay)
})
}
Promise.all([getSth(1000),getSth(2000),getSthFail(3000)]).then(res=>{
console.log("yeah")
},rej=>{
console.log("nooo")
})
ts 泛型
ts
function trying<T extends string | number>(i:T): T extends string ? boolean : string[] {
}
apply,bind和call
apply
Function 实例的 apply() 方法会以给定的 this 值和作为数组(或类数组对象)提供的 arguments 调用该函数。
js
const numbers = [5, 6, 2, 3, 7];
const max = Math.max.apply(null, numbers);
console.log(max);
// Expected output: 7
const min = Math.min.apply(null, numbers);
console.log(min);
// Expected output: 2
bind
Function 实例的 bind() 方法创建一个新函数,当调用该新函数时,它会调用原始函数并将其 this 关键字设置为给定的值,同时,还可以传入一系列指定的参数,这些参数会插入到调用新函数时传入的参数的前面。
js
const module = {
x: 42,
getX: function () {
return this.x;
},
};
const unboundGetX = module.getX;
console.log(unboundGetX()); // The function gets invoked at the global scope
// Expected output: undefined
const boundGetX = unboundGetX.bind(module);
console.log(boundGetX());
// Expected output: 42
call
Function 实例的 call() 方法会以给定的 this 值和逐个提供的参数调用该函数。
js
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = 'food';
}
console.log(new Food('cheese', 5).name);
// Expected output: "cheese"
Proxy
js
let star = {
name: 'jay',
age: 40,
phone: "12314562789"
}
let proxy = new Proxy(star, {
get: function (target, key, receiver) {
switch (key) {
case 'phone':
console.log("6")
break;
default:
console.log(Reflect.get(target, key, receiver))
return Reflect.get(target, key, receiver)
break;
}
// console.log(target,key,receiver)
},
set: function () {
}
})
console.log(proxy.name)
Flatten
js
function flatten(arr) {
let result = [];
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
result = result.concat(flatten(arr[i]));
} else {
result = result.concat(arr[i]);
}
}
return result;
}
const a = [1, [2, [3, 4]]];
console.log(flatten(a));
Curry
js
//函数柯里化封装(这个封装可以直接复制走使用)
function curry(fn, args) {
var length = fn.length;
var args = args || [];
return function () {
newArgs = args.concat(Array.from(arguments));
if (newArgs.length < length) {
return curry.call(this, fn, newArgs);
} else {
return fn.apply(this, newArgs);
}
}
}
Number.MAX_SAFE_INTEGER
//其他方法
function curry(fn,...bindArgs) {
return (...args)=>{
const allArgs = [...bindArgs,...args];
if(allArgs.length<fn.length) {
return curry(fn,...allArgs)
}else {
return fn(...args)
}
}
}
//需要被柯里化的函数
function multiFn(a, b, c) {
return a * b * c;
}
//multi是柯里化之后的函数
var multi = curry(multiFn);
console.log(multi(2)(3)(4));
console.log(multi(2, 3, 4));
console.log(multi(2)(3, 4));
console.log(multi(2, 3)(4));
// function sum1(a) {
// return function sum2(b) {
// return function sum3(c) {
// return function sum4(d) {
// return function sum5(e) {
// return a + b + c + d + e
// }
// }
// }
// }
// }
// console.log(sum1(1)(2)(3)(4)(5))
symbol
js
const symbolProp = Symbol('symbolProp');
const trySymbol = Symbol('hza')
const obj = {
[symbolProp]: 'Symbol property',
[trySymbol]: 'hza222',
[Symbol.iterator]: function () {
let index = 0
return {
next: () => {
return nextIndex < 4 ?
{ value: self.items[nextIndex++], done: false }
: { value: undefined, done: true }
}
}
},
stringProp: 'String property',
name: 'hza'
};