编辑代码

// 1、实现compose
function fn1(x) {
  return x + 1;
}
function fn2(x) {
  return x + 2;
}
function fn3(x) {
  return x + 3;
}
function fn4(x) {
  return x + 4;
}

function compose (...fns) {
    if (!fns.length) return v => v;
    if (fns.length === 1) return fns[0];
    return fns.reduce((prev, cur) => {
        return (...args) => {
            return prev(cur(...args));
        }
    })
}
console.log(compose(fn1, fn2, fn3, fn4)(1));

// 2、setTimeout实现setInterval
function myInterval (fn, wait = 1000) {
    let timer;
    async function interval () {
        await fn();
        timer = setTimeout(interval, wait);
    }
    return {
        stop: () => clearTimeout(timer),
    }
}

// 3、setInterval实现setTimeout
function myTimeout (fn, wait = 1000) {
    let timer;
    timer = setInterval(() => {
        fn();
        clearInterval(timer);
    }, wait);
}

/* 4、平时精度丢失问题如何解决?
0.1 + 0.2的问题
原因:
JS遵守IEEE(Institute of Electrical and Electronics Engineers) 754采用双精度存储,同时因为JS最大位数为52位,最大数是2^53,而数字转成
二进制时,会把超过的截断掉,导致累加后造成精度丢失。
平时可调用toFixed,小数可以是否相等可判断差值是否小于最小浮点数之间的差值,
*/
// 代码解决精度差的实现方法:
function changeNumber (num1, num2, op) {
    const num1Decimal = num1.toString().split('.')[1];
    const num2Decimal = num2.toString().split('.')[1];
    const num1DecimalLen = num1Decimal ? num1Decimal.length : 0;
    const num2DecimalLen = num2Decimal ? num2Decimal.length : 0;
    const power = Math.pow(10, Math.max(num1DecimalLen, num2DecimalLen));
    let result;
    switch (op) {
        case '+':
            result = (num1 * power + num2 * power) / power;
            break;
        case '-':
            result = (num1 * power - num2 * power) / power;
            break;
        case '*':
            result = (num1 * power * num2 * power) / power / power;
            break;
        case '/':
            result = (num1 * power) / (num2 * power);
            break;
        default:
            break;
    }
    return result;
}

// 5、发布订阅模式
class EventEmitter {
    constructor () {
        this.events = {};
    }

    on (type, callback) {
        if (!this.events[type]) {
            this.events[type] = callback;
        } else {
            this.events[type].push(callback)
        }

        return () => {
            this.off(type, callback);
        }
    }

    off (type, callback) {
        if (!this.events[type]) return;
        this.events[type] = this.events[type].filter((item) => callback !== item)
    }

    once (type, callback) {
        const fn = (...args) => {
            callback(...args);
            this.off(type, callback)
        }
        this.on(type, fn);
    }

    emit (type, ...args) {
        if (!this.events[type]) return;
        this.events[type].forEach((fn) => {
            fn.apply(this, args);
        })
    }
}

// 6、数组去重
function uniArr (arr) {
    return [...new Set(arr)];
}

// 7、数组扁平化
// reduce模式
function flatter (arr) {
    if (!arr.length) return;
    return arr.reduce((prev, cur) => {
        return Array.isArray(cur) ? [...prev, ...flatter[cur]] : [...prev, cur];
    }, []);
}
// 迭代模式
function flatter (arr) {
    if (!arr.length) return;
    while (arr.some((item) => Array.isArray(item))) {
        arr = [].concat(...arr)
    }
    return arr;
}

// 8、es5继承
function Parent (name) {
    this.name = name;
}
function Child (name) {
    Parent.call(this, name)
}
Child.prototype = Object(Parent.prototype);


// 9、实现new
function myNew (fn, ...args) {
    const obj = Object.create(fn.prototype);
    const res = fn.apply(obj, args);
    if (res && typeof res === 'object') {
        return res;
    }
    return obj;
}

// 10、深拷贝
function isObject (val) {
    return typeof val === 'object' && val !== null;
}

function deepClone (obj, hash = new WeakMap()) {
    if (!isObject(obj)) {
        return obj;
    }
    // 循环引用
    if (hash.has(obj)) {
        return hash.get(obj);
    }
    // 判断是对象还是数组
    const target = Array.isArray(obj) ? [] : {};
    Reflect.ownKeys(obj).forEach((item) => {
        target[item] = deepClone(item, hash);
    });
    return target;
}

// 11、instanceof
function myInstanceof (left, right) {
    const prototype = right.prototype;
    while (left) {
        if (left.__proto__ === prototype) return true
        left = left.__proto__;
    }
    return false
}


// 12、柯里化
function curry (fn, ...args) {
    const fnArgsLen = fn.length;
    let allArgs = [...args];
    const restFn = (...newArgs) => {
        // 判断总参数是否大于fnArgsLen
        allArgs = [...allArgs, ...newArgs];
        if (allArgs >= fnArgsLen) {
            return fn.apply(this, allArgs)
        } else {
            return restFn;
        }
    }
    return restFn;
}

// 12、冒泡排序(时间复杂度O(n^2))
function bubbleSort (arr) {
    const arrLen = arr.length;
    // 外层控制循环次数
    for (let i = 0; i < arrLen; i++) {
        for (let j = 0; j < arrLen - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                const temp = arr[j];
                arr[j] = arr[j + 1]; 
                arr[j + 1] = temp;
            }
        }
    }
    return arr;
}
console.log(bubbleSort([4,1,5,9,0,14,20]));

// 13、选择排序(时间复杂度O(n^2))
// 假设每次循环开始的那个数,最小,如果找到更小的,则与之对换
function selectSort(arr) {
    
    const arrLen = arr.length;
    for (let i = 0; i < arrLen; i++) {
        let minIndex = i;

        for (let j = minIndex; j < arrLen; j++) {
            // 找到比假设值还小的
            if (arr[j] < arr[minIndex]) {
                minIndex = j;
            }
        }

        // 判断是否不等于假设的index
        if (minIndex !== i) {
            // 对换
            const temp = arr[i];
            arr[i] = arr[minIndex];
            arr[minIndex] = temp;
        }
    }
    return arr;
}
console.log(selectSort([4,1,5,9,0,14,20]));

// 14、插入排序(时间复杂度O(n^2))
function insertSort (arr) {
    const arrLen = arr.length;
    for (let i = 1; i < arrLen; i++) {
        const target = arr[i];
        let j = i;
        while (j > 0 && arr[j - 1] > target) {
            arr[j] = arr[j - 1];
            j--;
        }
        arr[j] = target;
    }
    return arr;
}
console.log(insertSort([4,1,5,9,0,14,20]));

// 15、版本号排序的方法
['0.1.1', '2.3.3', '0.302.1', '4.2', '4.3.5', '4.3.4.5'].sort((a, b) => {
    let i = 0;
    const arr1 = a.split('.');
    const arr2 = b.split('.');
    while (arr1[i] || arr2[i]) {
        const s1 = arr1[i];
        const s2 = arr2[i];
        i++;
        if (s1 === s2) continue;
        return s2 - s1;
    }
});