SOURCE

class MyIterator {
    constructor(data) {
        this.index = 0;
        this.data = data;
    }

    next() {
        if (this.hasNext()) {
            return this.data[this.index++];
        }
        return null;
    }

    hasNext() {
        return this.index < this.data.length;
    }
}

const iterator = new MyIterator([1, 2, 3, 4, 5]);
while (iterator.hasNext()) {
    console.log(iterator.next());
}

//单例模式
//一个构造函数只有一个实例
class mySingle {
    constructor() {
        if (!mySingle.instance) {
            mySingle.instance = this;
        }
        return mySingle.instance;
    }
}
const s1 = new mySingle();
const s2 = new mySingle();
console.log(s1 == s2);

const object = {
    id: 1,
    get() {
        console.log(this.id);
    },
    set(value) {
        this.id += value;
    },
};

const personProxy = new Proxy(object, {
    get(target, property) {
        if (property === 'id') {
            console.log('Getting id');
            return target[property];
        }
        return Reflect.get(target, property);
    },
    set(target, property, value) {
        if (property === 'id') {
            console.log('Setting id');
            target[property] = value;
            return true; // 返回true表示设置操作成功
        }
        return Reflect.set(target, property, value);
    },
});

personProxy.get();
personProxy.set(5);
setTimeout(() => {
    personProxy.get();
}, 1000);

//flower proxy
const Target = function () {
    this.request = function () {
        console.log("代理送花");
    };
};

// // 定义代理对象
// const Proxy = function(target) {
//   this.target = target;

//   this.request = function() {
//     console.log("在请求之前执行一些操作");
//     this.target.request();
//     console.log("在请求之后执行一些操作");
//   };
// };

// // 创建目标对象实例
// const target = new Target();

// // 创建代理对象实例,并将目标对象传递给代理对象
// const proxy = new Proxy(target);

// // 通过代理对象发起请求
// proxy.request();

var obj = {
    val: 5,
}
function test(obj) {
    obj.val = 10;
    console.log(obj.val);
    var obj = { val: 20 };
    console.log(obj.val);
}
test(obj);

console.log(obj.val);
function test(obj) {
    console.log(typeof obj);
    function obj() { };
}
test({});

function args2Array(args) {
    var arr = [];
    for (var i = 0; i < args.length; i++) {
        arr[i] = args[i];
    }
}

function getGlobal() {
    return (function () { return this; }())
}
Array.prototype.myCall = function () {
    const thisArg = arguments[0];
    const args = [...arguments].slice(1);
    const invokeFunc = this;
    const isSrict = (function () { return this === undefined }());
    if (isStrict) {
        if (typeof thisArg === "number") {
            thisArg = new Number(thisArg);

        } else if (typeof thisArg === 'string') {
            thisArg = new String(thisAr);
        } else if (typeof thisArg === 'boolean') {
            thisArg = new Boolean(thisArg)
        }
    }
    if (!thisArg) {
        return invokeFunc(...args);
    }
    const uniqProp = Symbol();
    thisArg[uniqProp] = invokeFunc;
    return thisArg[uniqProp](...args);
}

Array.prototype.myApply = function (thisArg, args) {
    const invokeFunc = this;
    const isSrict = (function () { return this === undefined }())
    if (isSrict) {
        if (typeof thisArg === 'number') {
            thisArg = new Number(thisArg);
        } else if (typeof thisArg === 'string') {
            thisArg = new String(thisArg);
        } else if (typeof thisArg === 'boolean') {
            thisArg = new Boolean(thisArg);
        }
    }
    if (!thisArg) {
        return invokeFunc(...args);
    }
    const uniqProp = Symbol();
    this[uniqProp] = invokeFunc;
    return thisArg[uniqProp](...args);
}
//手写mybind

Function.prototype.myBind = function () {
    const thisArg = arguments[0];
    const boundParams = [...arguments].slice(1);
    const boundTargetFunc = this;
    if (typeof boundTargetFunc !== 'function') {
        throw new TypeError('the bound target function must be a function');
    }
    function fBound() {
        const restParams = [...arguments];
        const allParams = boundParams.concat(restParams);
        return boundTargetFunc.apply(this instanceof fBound ? this : thisArg, allParams);
    }
    fBound.prototype = Object.create(boundTargetFunc.prototype);
    return fBound;
}

// 定义一个示例函数
function greet(name) {
    console.log(`Hello, ${name}!`);
}

// 使用myBind创建一个绑定函数
const boundGreet = greet.myBind(null, 'John');

// 调用绑定函数
boundGreet(); // 输出: Hello, John!

//手写实现new

function myNew(Constructor, ...args) {
    const obj = Object.create(Constructor.prototype);
    Constructor.call(obj, ...args);
    return obj;
}

//use myNew

function Person(name) {
    this.name = name;
}

Person.prototype.greet = function () {
    console.log(`hello,my name is ${this.name}`);
}
const mike = myNew(Person, 'mike');
mike.greet();


//手写实现instanceof 

function myInstanceof(obj, ctor) {
    if (typeof ctor !== 'function') {
        throw new TypeError('the second paramater must be a function');
    }
    const rightProto = ctor.prototype;
    let leftProto = Object.getPrototypeOf();
    let isInstanceFlag = leftProto === rightProto;
    while (!isInstanceFlag && leftProto) {
        if (leftProto == rightProto) {
            isInstanceFlag = true;
        } else {
            leftProto = Object.getPrototypeOf(leftProto);
        }
    }
    return isInstanceFlag;
}

//手写 Promise.prototype.finally
//finally情况下,rejected优先

Promise.prototype.myFinally = function (onFinally) {
    return this.then(value => {
        return Promise.resolve(onFinally()).then(() => value);
    }),
        reason => {
            return Promise.resolve(onFinally()).THEN(() => { throw reason });
        }
}

//手写promise.all
// 这个主要是考察如何收集每㇐个 Promise 的状态变化,在最后㇐个 Promise 状态变化时,对外发出信号。 
// ● 判断 iterable 是否空 
// ● 判断 iterable 是否全部不是 Promise 
// ● 遍历,如果某项是 Promise,利⽤ .then 获取结果,如果 fulfilled,将 value 存在 values 中,并⽤fulfillCount 计数;如果是 rejected,直接 reject 
// reason。 
// ● 如果某项不是 Promise,直接将值存起来,并计数。 
// ● 等所有异步都 fulfilled,fulfillCount 必将是 iterable 的⻓度(在 onFulfilled 中判断 fulfillCount),此时可以 resolve values。


Promise.all = function (iterable) {
    const tasks = Array.from(iterable);
    if (tasks.length == 0) {
        return Promise.resolve([]);
    }
    if (tasks.every(task => !(task instanceof Promise))) {
        return Promise.resolve(tasks);
    }
    return new Promise((resolve, reject) => {
        const values = new Array(tasks.length).fill(null);
        const fulfillCount = 0;
        tasks.forach((task, index, arr) => {
            if (task instanceof Promise) {
                task.then(value => {
                    fulfillCount++;
                    values[index] = value;
                    if (fulfillCount === arr.length) {
                        resolve(values);
                    }
                }, reason => {
                    reject(reason);
                })
            } else {
                fulfillCount++;
                values[index] = task;
            }
        })
    })
}
//手写防抖节流
// 原理:
// 防抖( debounce ):不管事件触发频率多⾼,㇐定在事件触发 n 秒后才执⾏,如果你在㇐个事件触发的 n 秒内⼜触发了这个事件,就以新的事件
// 的时间为准, n 秒后才执⾏,总之,触发完事件 n 秒内不再触发事件, n 秒后再执⾏。(频繁触发就执⾏最后㇐次)
// 应⽤场景:
// 1. 窗⼝⼤⼩变化,调整样式 
// 2. 搜索框,输⼊后 1000 毫秒搜索 
// 3. 表单验证,输⼊1000 毫秒后验证 
// 4. 频繁点击按钮,使⽤防抖避免重复提交请求 
// 防抖实现:
// ● debunce 实则是个包装函数,通过传⼊操作函数和时间间隔,来返回㇐个新函数
// ● 新函数中主要是通过定时器来设置函数调⽤的频率 
// ● flag 只有第㇐次触发的时候会⽴即执⾏

function debounce(handler, ms, flag) {
    let timer = null;
    return function (...args) {
        clearTimeout(timer);
        if (flag && timer) {
            handler.apply(this, args);
        }
        timer = setTimeout(() => {
            handler.apply(this, args);
        }, ms)
    }
}
//demo
window.addEventListener('resize', debounce(handler, 1000));
function handler() {
    console.log('ok');
}

// 节流 
// 原理:
// 节流( throttle ):不管事件触发频率多⾼,只在单位时间内执⾏㇐次。(频繁触发,还是按照时间间隔执⾏)
// 应⽤场景:
// 1. ⿏标不断点击触发,mousedown(单位时间内只触发㇐次) 
// 2. 监听滚动事件,⽐如是否滑到底部⾃动加载更多,⽤throttle 来判断 
// 节流实现
// ● 和防抖不同的是,防抖中是取消定时器,节流中是定时器到时间⾃动执⾏,仅仅是将 timer 变量设置为 null 
// ● 时间戳版:第㇐次执⾏,最后㇐次不执⾏
//定时器版,第一次不执行,最后一次执行

//时间戳版
function throlttle(handler, ms) {
    let pre = 0;
    return function (...args) {
        if (Date.noew() - pre > ms) {
            pre = Date.now();
            handler.apply(this, args);
        }
    }
}

//定时器版
function throttle(handler, ms) {
    let timer = null;
    return function (...args) {
        if (!timer) {
            timer = setTimeout(() => {
                timer = null;
                handler.apply(this, args);
            }, ms)
        }
    }
}

//手写深拷贝,考虑多种数据类型的处理

function deepClone(val) {
    const type = getType(val);
    if (type === "object") {
        const result = {};
        Object.keys(val).forEach(key => {
            result[key] = deepClone(val[key]);
        })
    } else if (type === 'array') {
        return val.map(item => deepClone(item));
    } else if (type === "date") {
        return new Date(val.getTime());
    } else if (type === "regexp") {
        return new RegExp(val.source, val.flags);
    } else if (type === "function") {
        return eval("(" + val.toString() + ")");
    } else if (type === "map" || type === "set") {
        return new val.constructor(val);
    } else {
        return val;
    }
}

//实现柯里化

//按定义实现
function curry(fn, presetParam) {
    return function () {
        return fn.apply(this, [preseParam, ...arguments])
    }
}
//扩展多参数
function curry1(fn, ...args) {
    return function () {
        return fn.apply(this, [...args, ...arguments]);
    }
}

//定长柯里化,执行时机判断

function curry2(fn, ...args) {
    const len = fn.length;
    return function () {
        const allArgs = [...args, ...arguments];
        if (allArgs.length >= len) {
            return fn.apply(this, allArgs);
        } else {
            return curry2.call(null, fn.bind(this), ...args)
        }
    }
}
//虽然发布订阅out,但是还是记录一下

class Listener {
    constructor(id, eventName, callback) {
        this.id = id;
        this.eventName = eventName;
        this.callback = callback;
    }
}

class EventBus {
    constructor() {
        this.events = {};
        this.autoIncreaseId = 1;
    }
    addListener(listener) {
        if (this.evnents[listener.eventName]) {
            this.events[listener.eventName].push(listener);
        } else {
            this.events[listener.eventName] = [listener];
        }
        return listener;
    }
    on(eventName, handler) {
        const listener = new Listener(this.autoIncreaseId++, eventName, handler);
        return this.addListener(listener);
    }
    emit(eventName,handler){
        if(this.events[eventName]){
            this.events[eventName].forEach(({callback})=>{
                callback(...args);
            })
        }
    }
    off(eventName,listener){
        const listeners=this.events[eventName];
        if(listeners){
            const index=listeners.findIndex(l=>l.id===listener.id);
              if(index!==-1){
                  listeners.splice(index,1)
              }
        }
      
    }
    remove(eventName){
        if(this.events[eventName]){
            delete this.events[evenName];
        }
    }
    once(eventName,handler){
        const that=this;
        const id=this.autoIncreaseId++;
        const onceCallback=function(){
            handler(...arguments);
            const index=that.events[eventName].findIndex(l=>l.id===id);
            that.events[eventName].splice(index,1)
        }
        const listener=new Listener(id,eventName,onceCallback);
        return this.addListener(listener);
    }

}
console 命令行工具 X clear

                    
>
console