手写代码

/*
 * @Author: Mr.pz
 * @Date: 2021-01-29 15:02:35
 * @Last Modified by: Mr.pz
 * @Last Modified time: 2021-01-30 10:07:17
 * 手写代码有一个很重要的步骤,是先想你要实现什么,先把参数和思路理清
 */

// 手写 wait(sleep)
function wait(time, msg) {
  return new Promise((res) => {
    setTimeout(() => {
      res(msg);
    }, time);
  });
}

// wait(3000, "hello").then((res) => {
//   console.log(res);
// });

// 深拷贝对象

/**
 * 在访问,增加,删除,有不同的时间复杂度
 * 访问: 数组中有下标  A[3],A[10000],数组的访问时 O(1), 而链表(只考虑单项链表),需要一个个往下访问 O(n)
 * 增加,删除: 数组需要有一个“插队”的操作O(n),所有人都需要往后挪一位,而链表只需要改变相应的指针O(1)。
 */

// promise

/**
 * apply,call,bind
 * 功能:改变this指向
 * a.apply(对象,参数),对象如果是null,或者等于 undefined,则将对象赋值为 window,在函数上新增,所以是 Function.prototype.MyApply
 * call 相对应是参数的不同
 * bind 储存一个闭包
 */

//  定义一个对象
const obj = {
  b: 1,
};
// 另外一个对象
const obj2 = {
  b: 2,
  fun: function (args) {
    // console.log(args); // [1,2,3]
    // console.log(this.b); // 打印为1
  },
};
//  ====> myApply
Function.prototype.myApply = function (context) {
  // 如果第一个参数没有传值,或者为undefined,则取window
  if (context === null || typeof context === "undefined") {
    context = window;
  }

  // this 指的是调用 myCall的函数
  context.fn = this;

  // 取除context以外的参数
  let args = [...arguments].slice(1);
  let result;
  if (args) {
    // 这里的执行会将函数中的 this.x 的值修改到原对象中
    result = context.fn(...args);
  } else {
    result = context.fn();
  }
  // 在context中执行这个函数

  // 执行完后还原原对象
  delete context.fn;

  // 将函数值返回
  return result;
};

Function.prototype.myCall = function (context) {
  // 如果第一个参数没有传值,或者为undefined,则取window
  if (context === null || typeof context === "undefined") {
    context = window;
  }

  // this 指的是调用 myCall的函数
  context.fn = this;

  // 取除context以外的参数
  let args = [...arguments].slice(1);

  // 在context中执行这个函数 // 这里的执行会将函数中的 this.x 的值修改到原对象中
  // 如果 fn返回的是一个对象,则result是这个对象
  let result = context.fn(...args);

  // 执行完后还原原对象
  delete context.fn;

  // 将函数值返回
  return result;
};

// bind会对this做一个缓存操作,属于非立即执行
Function.prototype.MyBind = function (context) {
  if (typeof this !== "function") {
    throw new TypeError();
  }
  let _this = this;

  let args = [...arguments].slice(1);

  return function F() {
    return _this.apply(context, args.concat([...arguments]));
  };
};

/**
 * new
 * 创建一个空对象
 * 将所有传进去的函数在当前空对象上执行,
 * 需要注意的是,如果函数执行的返回值是 对象,则直接返回这个对象,而不是返回这个处理后的空对象
 */
function _new() {
  // 创建一个新对象
  let newObj = {};
  // 获取构造函数   fun a()
  let Constructor = Array.prototype.shift.call(arguments);
  // 连接新对象原型,新对象可以访问原型中的属性, 原型链指向
  newObj.__proto__ = Constructor.prototype;
  // 执行构造函数,即绑定 this,并且为这个新对象添加属性 newObj 获得 Constructor 的this 对象
  let ret = Constructor.apply(newObj, arguments);
  // 返回该对象 如果构造函数中返回的对象,则返回对象,否则返回newObj
  return typeof ret === "object" ? ret : newObj;
}

function a() {
  this.b = 1;
}

const c = _new(a);

/**
 * 实现
const add3 = add(1)(2)
const add8 = add(3)+5
const add10 = add(1,2,3)(4)
 */

function add(...args) {
  const fn = add.MyBind(null, ...args);
  // => add.bind(null,...args) = fn
  /**
   * function F() {
    return add.apply(context, args.concat([...arguments]));
  };
   */
  // => add.bind(null, ...args)(2)  add
  fn.sumOf = () => {
    console.log(args);
    return args.reduce((prev, next) => {
      return prev + next;
    }, 0);
  };

  return fn;
}

add(1)(2)(3).sumOf();
/**
 * 每个 N 秒执行一次,如果有重新出发,这个N将被重置
 * 可以看成一个弹簧,你一定时间内,高频率重复按压,这个弹簧不会被弹起复原(触发)。一旦你频率降低,这个弹簧就会被触发。
 */

function debounce(fn, time) {
  let timeout = null;
  return function () {
    if (timeout !== null) clearTimeout(timeout);
    timeout = setTimeout(fn, time);
  };
}
/**
 * 每个N秒必须执行一次。不管期间的重复触发,第一次必须执行
 * throttle
 */
function throttle(fn, time) {
  let timer = null,
    firstTime = true;
  return function () {
    if (firstTime) {
      fn();
      return;
    }
    if (timer) {
      return;
    }
    timer = setTimeout(() => {
      clearTimeout(timer);
      timer = null;
      fn();
    }, time);
  };
}

/**
 * 判断是否是一个数组
 * instanceof
 * let arr = [] arr.constructor === Array
 * Array.isArray
 * Object.prototype.toString.call(arg) === '[Object Array]'
 */

 // Lazy_Man('榕').rest(5).eat('面线糊')

// Lazy_Man('榕').restFirst(5).eat('面线糊')

function LazyMan(name) {
  this.task = [];
  const that = this;
  setTimeout(() => {
    console.log("hi, this is lazy man", name);
    that.next();
  }, 0);
}

LazyMan.prototype.next = function () {
  const fn = this.task.shift();
  fn && fn();
};

LazyMan.prototype.eat = function (name) {
  var self = this;
  var fn = (function (name) {
    return function () {
      console.log("Eat " + name + "~");
      self.next();
    };
  })(name);
  this.task.push(fn);
  return this;
};

LazyMan.prototype.rest = function (time) {
  const that = this;
  const fn = ((time) => {
    return function () {
      setTimeout(() => {
        that.next();
      }, time * 1000);
    };
  })(time);
  this.task.push(fn);
  return this;
};

LazyMan.prototype.restFirst = function (time) {
  const that = this;
  const fn = ((time) => {
    return function () {
      setTimeout(() => {
        that.next();
      }, time * 1000);
    };
  })(time);
  this.task.unshift(fn);
  return this;
};

function Man(name) {
  return new LazyMan(name);
}
Man("jack").eat("棉线").restFirst(2).rest(10).eat("大米");


// 手写 instanceof

function MyInstanceof(target, origin) {
  while (target.__proto__) {
    if (target.__proto__ === origin.prototype) {
      return true;
    }
    target = target.__proto__;
  }
  return false;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值