// 手动实现一个 myCall 函数
Function.prototype.myCall = function(context) {
// 判断调用者的类型
if (Object.prototype.toString.call(this).slice(8, -1) !== 'Function') {
console.error('只有函数有Call方法');
return;
}
// 缺省的情况用window
context = context ? Object.create(context) : window;
const args = Array.from(arguments).slice(1);
context.fn = this;
const result = context.fn(...args);
delete context.fn;
return result;
}
// 手动实现一个 apply
Function.prototype.myApply = function(context) {
// 判断调用者的类型
if (Object.prototype.toString.call(this).slice(8, -1) !== 'Function') {
console.error('只有函数有Call方法');
return;
}
context = context ? Object.create(context) : window;
const args = arguments[1];
context.fn = this;
const result = context.fn(...args);
delete context.fn;
return result;
}
// 手写Bind
Function.prototype.myBind = function(context) {
// 判断调用者的类型
if (Object.prototype.toString.call(this).slice(8, -1) !== 'Function') {
console.error('只有函数有Call方法');
return;
}
context = context ? Object.create(context) : window;
const args = Array.from(arguments).slice(1);
const self = this;
// 返回一个函数
const returnFn = function() {
const extArgs = Array.from(arguments);
// 兼容一下通过new的构造函数进来的情况
self.apply(this instanceof returnFn ? returnFn : this, [...args, ...extArgs]);
}
// 保持原型,防止原型丢失。
const fn = function() {};
fn.prototype = this.prototype;
returnFn.prototype = new fn(); // 用一个中间函数方式原型链丢失
return returnFn
}
// 手写new关键字
function _new(fn, ...args) {
// 1. 创建对象,并且把prototype指向fn
const obj = Object.create(fn.prototype);
// 2. 调用构造函数
const ret = fn.apply(obj, args);
// 3. 构造函数构造出来的如果是对象,直接返回,否则返回执行fn.apply之前的obj
return obj instanceof Object ? ret : obj;
}
// 防抖
function debounce(fn, delay) {
let timer;
return function(...args) {
// 如果有定时器,清除,重新计算时间
if (timer) {
clearTimeout(timer);
}
setTimeout(() => {
fn.apply()
}, delay)
}
}
// 节流
function throttle(fn, wait) {
let canRun = true;
return function(...args) {
if (!canRun) {
return;
}
// 继续上锁
canRun = false;
setTimeout(() => {
fn.apply(this, ...args);
canRun = true;
},wait)
}
}
function cloneDeep(target, cache = new WeakMap()) {
// 判断 null 和 非 Object场景
if (target === null || typeof target !== 'object') {
return target;
}
// 处理 Date、RegExp场景
if (target instanceof Date) {
return new Date(target);
}
if (target instanceof RegExp) {
return new RegExp(target);
}
// 处理对象,首先需要防止循环引用 a.b = a;
if (cache.has(target)) {
return cache.get(target);
}
// 重新创建对象, 保持原型链
const obj = new target.contructor();
// 缓存一下对象
cache.set(target, obj);
Object.keys(key => {
// 递归调用一下
obj[key] = cloneDeep(target[key], cache);
});
return obj;
}
function sayHello(param1, param2, param3) {
console.log(this.name, param1, param2);
}
const thisObj = {
name: 'zaoren'
}
// sayHello.call(thisObj, 'day', 'day up');
sayHello.myCall(thisObj, 'day', 'day up');
sayHello.myApply(thisObj, ['day', 'day up']);
const wSayHello = sayHello.myBind(thisObj, 'day')('day up');
function Student(age) {
this.name = 'zaoren';
this.age = age;
return this;
}
const student = _new(Student, '18');
console.log('student', student);
// 测试
const obj = { name: 'Jack', address: { x: 100, y: 200 } }
obj.a = obj // 循环引用
const newObj = cloneDeep(obj)
console.log(newObj.address === obj.address) // false
console