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

1、手写 new 的过程

const myNew = (fn, ...args) => {
    // 创建一个空对象
    const obj = {}
    // 设置空对象的原型
    obj.__proto__ = fn.prototype
    fn.apply(obj, args)
    return obj
}

2、instanceof关键字

// 通过判断对象的原型链中是不是能找到类型的 prototype。
const myInstanceof = (left, right) {
    // 基本数据类型直接返回false
    if (typeof left !== 'object' || left === null) return false
    // getProtypeOf是Object对象自带的一个方法,能够拿到参数的原型对象
    let proto = Object.getPrototypeOf(left)
    while (true) {
        // 查找到尽头,没找到
        if (proto == null) return false
        // 找到相同的原型对象
        if (proto == right.prototype) return true
        proto = Object.getPrototypeOf(proto)
    }
}

console.log(myInstanceof("111", String))  //false
console.log(myInstanceof(new String("111"), String))  //true

详见: 浅谈 instanceof 原理

3、防抖函数

// func是用户传入需要防抖的函数
// wait是等待时间, 默认500
const debounce = (func, wait = 500) => {
    // 缓存一个定时器
    let timer = 0
    // 这里返回的函数是每次用户实际调用的防抖函数
    return function(...args) {
        // 如果已经设定过定时器就清空上一次的定时器
        if (timer) clearTimeout(timer)
        // 开始一个新的定时器,延迟执行用户传入的方法
        timer = setTimeout(() => {
            func.apply(this, args)
        }, wait)
    }
}

4、节流函数

// func是用户传入需要节流的函数
// wait是等待时间, 默认500
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 中,如何判断两个对象是否相等?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Coder_lixc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值