Skip to content

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 实现,两者目的都是降低回调执行频率和节省计算资源。
  • 不同点:
  1. 函数防抖,在一段连续操作结束后,处理回调,利用clearTimeout和 setTimeout实现。函数节流,在一段连续操作中,每一段时间只执行一次,频率较高的事件中使用来提高性能
  2. 函数防抖关注一定时间连续触发的事件,只在最后执行一次,而函数节流一段时间内只执行一次
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'
};