手写常见js方法

1. 实现new方法

function objectCreate(Constructor, ...rest) {
  // 以构造函数的原型创建新对象
  var obj = Object.create(Constructor.prototype);
  // 以obj为this上下文来执行构造函数
  var res = Constructor.apply(obj, rest);
  // 根据new生成对象的原则,若有返回值为对象,则返回该结果,若没有,则返回开始生成的对象
  return typeof ret === 'object' ? res : obj
}

// 示例
function MyConstructor() {...}
var instance = objectCreate(MyConstructor, ...)

2.实现call方法

Function.prototype.myCall = function(context, ...args) {
  // 第一个参数为执行上下文,若为null则指向window
  var context = context || window;
  // this为执行的函数fn
  context.fn = this; 
  // 在context上下文中执行fn函数,并传入参数
  var result = context.fn(...args)
  delete context.fn
  return result
}

3. 实现apply方法

Function.prototype.myApply = function(context, args) {
  // 第一个参数为执行上下文,若为null则指向window
  var context = context || window;
  // this为执行的函数fn
  context.fn = this; 
  // 在context上下文中执行fn函数,并传入参数
  var result = context.fn(...args)
  delete context.fn
  return result
}

4.实现bind方法

Function.prototype.myBind = function(context, ...args1) {
  const _this = this
	var Func = function(...args2) {
    return _this.apply(this instanceOf Func ? this : context, args1.concat(args2))
  }
  Func.prototype = this.prototype
  return Func
} 

注: this instanceOf Func ? this : context为了判断调用的方法是否为构造函数,如果是构造函数,则用new来调用, 此时上下文this不再是绑定的this,而是最后调用该函数的对象

5. 实现防抖方法

  • 不管事件触发频率多高,一定在事件触发n秒后才执行,如果你在一个事件触发的 n 秒内又触发了这个事件,就以新的事件的时间为准,n秒后才执行,总之,触发完事件 n 秒内不再触发事件,n秒后再执行。
  • 关联记忆: 函数防抖就是法师发技能的时候要读条,技能读条没完再按技能就会重新读条。
function debounce(fn, wait) {
	var timer = null;
  return function(...args) {
    var context = this;
    clearTimeout(timer);
    // 当timer为空时代表第一次执行, 立即进行执行
    if (!timer) {
      fn.call(context, ...args)
    }
    timer = setTimeout(() => {
      	fn.call(context, ...args)
      }, wait)
  }
}

6.实现节流方法

  • 不管事件触发频率多高,只在单位时间内执行一次。
// 方法1,第一次不会立即执行, 最后一次一定触发
function throttle(fn, wait) {
	var timer = null;
  return function(...args) {
    var context = this;
    if (timer) return
    timer = setTimeout(() => {
      fn.call(context, ...args)
      timer = null
    }, wait)
  }
}

// 方法2, 第一次触发会立即执行, 最后一次不会触发
function throttle2 (fn, wait) {
  var prevTime;
  return function(...args) {
    var context = this;
    var nowTime = +new Date();
    if (!preTime || nowTime - preTime > wait) {
      fn.call(context, ...args)
      prevTime = nowTime;
    }
  }
}

// 方法3,结合版,第一次和最后一次触发事件都会执行
function throttle3 (fn, wait) {
  var timer = null;
  var prevTime = 0;
  return (...args) => {
    var context = this;
    var nowTime = +new Date(); 
    if (nowTime - prevTime > wait) {
      clearTimeout(timer);
      timer = null;
      fn.apply(context, args);
      prevTime = nowTime;
    } else {
      timer = setTimeout(function() {
        fn.apply(context, args);
      }, wait)
    }
  }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值