JavaScript进阶的手写知识点,你会写几个?

1、手写 new 的过程

const myNew = (fn, ...args) => {
    const obj = {}
    obj.__proto__ = fn.prototype
    fn.apply(obj, args)
    return obj
}
复制代码

2、instanceof关键字

const instanceOf = (father, child) => {
    const fp = father.prototype
    var cp = child.__proto__
    while (cp) {
        if (cp === fp) {
            return true
        }
        cp = cp.__proto__
    }
    return false
}
复制代码

3、防抖函数

const debounce = (func, wait = 500) => { 
    let timer = 0
    return function(...args) { 
        if (timer) clearTimeout(timer) 
        timer = setTimeout(() => { 
            func.apply(this, args) 
        }, wait) 
    } 
}
复制代码

4、节流函数

const throttle = (func, wait = 500) => {
    let lastTime = 0
    return function(...args) {
        let now = +new Date()
        if (now - lastTime > wait) { 
            lastTime = now
            func.apply(this, args)
        }
    }
} 


setInterval(
    throttle(() => { 
        console.log(1) 
    }, 3000),
    1
)
复制代码

5、手写 call()

Function.prototype.myCall = function(context) {
    if (typeof this !== 'function') {
        throw new TypeError('Error')
    }
    context = context || window
    // 谁调用call方法,this就指向谁
    context.fn = this  
    // 去掉所有参数中第一参数(指定的对象)
    const args = [...arguments].slice(1)
    const result = context.fn(...args)
    delete context.fn
    return result
}
复制代码

6、手写 apply()

Function.prototype.apply = function (context) {
    if (typeof this !== 'function') {
        throw new TypeError('Error')
    }
    context = context || window
    context.fn = this
    let result
    // 处理参数和 call 有区别,apply只有两个参数,第一个是对象,第二个是数组
    if (arguments[1]) {
        result = context.fn(...arguments[1])
    } else {
        result = context.fn()
    }
    delete context.fn
    return result
}
复制代码

7、手写 bind()

Function.prototype.bind = function(context) {
    if (typeof this !== 'function') {
        throw new TypeError('Error')
    }
    const _this = this
    const args = [...arguments].slice(1)
    // 返回一个函数
    return function F() {
        // 因为返回了一个函数,我们可以 new F(),所以需要判断
        if (this instanceof F) {
            // 忽略传入的this
            return new _this(...args, ...arguments)
        }
        // 直接调用,将两边的参数拼接起来
        return _this.apply(context, args.concat(...arguments))
    }
}
复制代码

详见: call、apply和bind的区别以及源码解析

8、数组去重

// 第一种:reduce去重
const quchong1 = (arr) => {
    const newArr = []
    arr.reduce((pre, next) => {
        if (!pre[next]) {
            pre[next] = 1
            newArr.push(next)
        }
        return pre
    }, {})
    return newArr
}

// 第二种:Set去重
const quchong2 = (arr) => {
    return [...new Set(arr)]
}
复制代码

9、数组对象去重

let arr = [{
  key: '01',
  value: '西施'
}, {
  key: '02',
  value: '王昭君'
}, {
  key: '03',
  value: '杨玉环'
}, {
  key: '04',
  value: '貂蝉'
}, {
  key: '01',
  value: '西施'
}, {
  key: '01',
  value: '西施'
}];

let obj = {};
arr = arr.reduce((item, next) => {
  obj[next.key] ? '' : obj[next.key] = true && item.push(next);
  return item;
}, []);
console.log(arr); // [{key: "01", value: "西施"},{key: "02", value: "王昭君"},{key: "03", value: "杨玉环"},{key: "04", value: "貂蝉"}]
复制代码

10、简易版深拷贝

/*
 * @param x {Object} 对象1
 * @param y {Object} 对象2
 * @return  {Boolean} true 为相等,false 为不等
 */
export const deepEqual = (x, y) => {
  // 指向同一内存时
  if (x === y) {
    return true;
  } else if ((typeof x == "object" && x != null) && (typeof y == "object" && y != null)) {
    if (Object.keys(x).length !== Object.keys(y).length) {
      return false;
    }
    for (var prop in x) {
      if (y.hasOwnProperty(prop)) {  
        if (!deepEqual(x[prop], y[prop])) return false;
      } else {
        return false;
      }
    }
    return true;
  } else {
    return false;
  }
}
复制代码

详见: JavaScript 中,如何判断两个对象是否相等?

猜你喜欢

转载自juejin.im/post/7036546109543546910