手写 new
function myNew(fn, ...args) {
let obj = Object.create(fn.prototype);
let res = fn.apply(obj, args);
if (res && ['function', 'object'].includes(typeof res) {
return res;
}
return obj;
}
手写 call
Function.prototype.myCall = function(context, ...args) {
if (!content || context === null) {
context = window;
}
let fn = symbol();
context[fn] = this;
return context[fn](...args);
}
手写 apply
Function.prototype.myApply = function(context, args) {
if (!content || context === null) {
context = window;
}
let fn = symbol();
context[fn] = this;
return context[fn](...args);
}
手写 bind
传统使用 bind方法,返回的是一个函数,需要等待后续的调用
Function.prototype.myBind = function(context, ...args) {
let fn = symbol();
context[fn] = this;
let _this = this;
const result = function(...innerArgs) {
//兼容 new构建
if (this instanceof _this) {
this[fn] = _this;
this[fn](...[...args, ...innerArgs]);
}
else {
context[fn](...[...args, ...innerArgs]);
}
}
result.prototype = Object.create(this.prototype);
return result;
}
手写实现数组扁平化
//使用while循环
while(arr.some(a => Array.isArray(a))) {
arr = [].concat(...arr);
}
//使用传统的flat函数
arr.flat(Infinity)
//使用reduce实现
function _flat(arr) {
return arr.reduce(
(pre, cur) => pre.concat(Array.isArray(cur) ? _flat(cur) : cur) ,
[]
)
}
手写 setTimeout模拟 setInterval
function myInterval(fn, t) {
let timer;
function interval() {
//先执行方法
fn();
timer = setTimeout(interval, t);
}
interval();
return {
cancel: () => clearTimeout(timer);
}
}
手写防抖
function debounce(fn, wait) {
let timer;
return function(...args) {
const ctx = this;
if (timer) {
clearSetTimeout(timer);
timer = undefined;
}
timer = setTimeout(() => {
fn.apply(ctx, args);
}, wait)
}
}
手写节流
function throttle(fn, gap) {
let curTime = Date.now();
return function(...args) {
let nowTime = Date.now();
const ctx = this;
if (nowTime - curTime >= gap) {
curTime = Date.now();
return fn.apply(ctx, args);
}
}
}
手写深拷贝
function isObject(val) {
return typeof val === 'object' && val !== null;
}
function deep(obj) {
//如果不是对象类型
if (!isObject(obj)) return obj;
let target = Array.isArray(obj) ? [] : {};
Reflect.ownkeys(obj).forEach((item) => {
if (isObject(obj[item])){
target[item] = deep(obj[item])
}
else {
target[item] = obj[item];
}
})
return target;
}
手写 发布订阅
class EventEmitter {
constructor() {
this.events = {}
}
//订阅
on(type, cb) {
if (!this.events[type]) {
this.events[type] = [];
}
this.events[type].push(cb);
}
//删除
off(type, cb) {
if (!this.events[type]) return;
this.events[type] = this.events[type].filter(i => i !== cb);
}
//发布
emit(type, ...args) {
if (!this.events[type]) return;
this.events[type].forEach(fn => fn.apply(this, args))
}
}