/*
* @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;
}
手写代码
最新推荐文章于 2023-03-16 16:33:15 发布