js手写代码

93 阅读2分钟

手写代码

1. 函数的call() / apply() / bind()

/*
1. 自定义函数对象的call方法
*/
Function.prototype.call = function(obj,...args) {
    // 如果传入的是null 或 undefined  this指向为window
    if(obj === null || obj === undefined ){
        return this(...args)
    }
    // 给obj添加一个方法: 属性名任意, 属性值必须调用当前call的函数对象
    obj.tempFn = this
    // 通过obj调用这个方法
    const result = obj.tempFn(...args)
    // 删除新添加的方法
    delete obj.tempFn
    // 返回函数调用的结果
    return result
}

/*
2. 自定义函数对象的apply方法
*/
Function.prototype.apply = function (obj,args) {
    // 如果传入的是null/undefined, this指向window
    if(obj === null || obj === undefined ){
        return this(...args)
    }
    // 给obj添加一个方法: 属性名任意, 属性值必须当前调用call的函数对象
    obj.tempFn = this
    // 通过obj调用这个方法
    const result = obj.tempFn(...args)
    // 删除新添加的方法
    delete obj.tempFn
    // 返回函数调用的结果
    return result
}

2. 手写防抖节流

/*
1. 节流函数  仅执行最后一次
*/
function throttle (callback,time){
    // 用于保存处理时间 初始值为0
    let start = 0
    // 返回事件监听函数 => 每次事件发生都会执行
    return function (e) {
        // 发生事件的当前时间
        const current = Date.now()
        // 与上一次处理事件的时差大于time的时间
        if(current - start > time){
            // 执行处理事件函数
            callback.call(e.target,e)
            // 保证当前时间
            start = current
        }
    }
}

/*
2. 防抖函数 每间隔一段时间执行一次
*/
function debounce (callback , time){
    return function(e){
        // 如果还有未执行的定时器, 清除它
        if(callback.timeoutId){
           clearTimeout(callback.timeoutId)
        }
        // 启动延时time的定时器 并且保证定时器id
        callback.timeoutId = setTimeout(() => {
            // 执行处理事件的函数
            callback.call(e.target,e)
            // 删除保存的定时器id
            delete callback.timeoutId
        },time)
    }
}

3. 数组去重

/*
方法2: 利用forEach() + 对象容器
说明: 只需一重遍历, 效率高些
[1, 3, 5, 3]
*/
function unique2 (array) {    
  const arr = []
  const obj = {}
  array.forEach(item => {
    if (!obj[item]) {
      // if (!obj.hasOwnProperty(item)) {// 不用遍历就能判断出是否已经有了
      obj[item] = true
      arr.push(item)
    }
  })
  return arr
}
                
// 以空间换时间
/*
方法3: 利用ES6语法
    1). from + Set
    2). ... + Set
    说明: 编码简洁
*/
function unique3 (array) {
  // return Array.from(new Set(array))
  return [...new Set(array)]
} 

4. 数据扁平化

// var arr = [1,[[2,[3,4],5]]                 
function fn (arr){
    const res = arr.map(item => Array.isArray(item)? fn(item):item )
    return res
}
fn(arr)

5. 深拷贝

/*
1. 简易版   缺点: 不能深拷贝函数类型
*/
function deepClone1 (data){
    return JSON.parse(JSON.stringify(data))
}
/*
2. 原生js实现
*/
function deepClone2 (data){
  const type = getType(target)
  if (type==='Object' || type==='Array') {
    const cloneTarget = type === 'Array' ? [] : {}
    for (const key in target) {
      if (target.hasOwnProperty(key)) {
        cloneTarget[key] = deepClone2(target[key])
      }
    }
    return cloneTarget
  } else { // 基本类型 / function
    return target
  }
}