SOURCE

// [1] 斐波那契数列
// [2] 杨辉三角
// [3] 防抖节流
// [4] call、apply、bind
// [5] Promise.all和Promise.race
// [6] 函数柯里化
// [7] 深拷贝
// [8] 类型判断函数
// [9] 订阅发布模式
// [10] 数组去重
// [11] 数组降维
// [12] new
// 斐波那契数列 fn(n-2) + fn(n-1)
function fb(n) {
    if (n < 2) {
        return 1
    } else {
        return fb(n - 2) + fb(n - 1)
    }
}
function testFbFn(n) {
    var arr = [];
    for (var i = 0; i < n; i++) {
        arr.push(fb(i))
    }
    return arr;
}
console.log(testFbFn(10))

// 杨辉三角 fn(m-1,n-1) + fn(m-1, n) 
function yhsj(m, n) {
    if (n == 0) {
        return 1;
    } else if (m == n) {
        return 1
    } else {
        return yhsj(m - 1, n - 1) + yhsj(m - 1, n);
    }
}
function testYhsjFn(n) {
    for (var i = 0; i < n; i++) {
        var arr = [];
        for (var j = 0; j <= i; j++) {
            arr.push(yhsj(i, j));
        }
        console.log(arr)
    }
}
testYhsjFn(10);

// 防抖节流
// 防抖1:延时执行
function debunce1(fn, wait) {
    let timer;
    return function () {
        let _this = this;
        let args = [...arguments]
        if (timer) {
            clearTimeout(timer);
            timer = null;
        }
        timer = setTimeout(() => {
            fn.apply(_this, args)
        }, wait)
    }
}
// 防抖2:立即执行
function debunce2(fn, wait) {
    let timer;
    return function () {
        let _this = this;
        let args = [...arguments]
        if (timer) {
            clearTimeout(timer)
        }
        timer = setTimeout(() => {
            timer = null
        }, wait)
        let applyNow = !timer;
        if (applyNow) {
            fn.apply(_this, args)
        }
    }
}
// 节流1:定时器
function throttle1(fn, wait) {
    let timer;
    return function () {
        let _this = this;
        let args = [...arguments];
        if (!timer) {
            timer = setTimeout(() => {
                fn.apply(_this, args)
                timer = null;
                clearTimeout(timer)
            }, wait)
        }

    }
}
// 节流2:时间间隔
function throttle2(fn, delay) {
    let curTime = Date.now();
    return function () {
        let _this = this;
        let args = [...arguments];
        let now = Date.now();
        if (now - curTime >= delay) {
            curTime = Date.now();
            fn.apply(_this, args)
        }
    }
}

// call、apply、bind
Function.prototype.myApply = function (context) {
    if (typeof this !== "function") {
        return;
    }
    return function () {
        let result;
        context = context || window;
        context.fn = this;
        if (arguments[1]) {
            result = context.fn(...arguments[1])
        } else {
            result = context.fn();
        }
        delete context.fn;
        return result
    }
}
Function.prototype.myCall = function (context) {
    if (typeof this !== "function") {
        return;
    }
    return function () {
        let result;
        context = context || window;
        context.fn = this;
        let args = [...arguments].slice(1);
        result = context.fn(args)
        delete context.fn;
        return result
    }
}
Function.prototype.myBind = function (context) {
    if (typeof this !== "function") {
        return;
    }
    let args = [...arguments].slice(1);
    let fn = this;
    return function Fn() {
        return fn.apply(this instanceof Fn ? this : context, args.cancat(arguments))
    }
}

// Promise.all和Promise.race
function PromiseAll(promises) {
    return new Promise((resolve, reject) => {
        let result = [];
        let n = 0;
        promises.forEach(item => {
            Promise(item).then(res => {
                n++;
                result.push(res)
                if (n === promises.length) {
                    resolve(result)
                }
            }).catch(err => {
                reject(err)
            })
        })
    })
}
function PromiseRace(promises) {
    return new Promise((resolve, reject) => {
        promises.forEach((item, index) => {
            Promise(item).then(res => {
                resolve(res)
            })
        }).catch(err => {
            reject(err)
        })
    })
}
// 函数柯里化
function curry(fn, args) {
    let length = fn.length;
    args = args || [];
    return function () {
        let subArgs = args.concat([...arguments]);
        if (subArgs.length >= length) {
            return fn.apply(this, subArgs)
        } else {
            return curry.call(this, fn, subArgs)
        }
    }
}

// 深拷贝
function deepClone(obj) {
    var newObj = {};
    Object.keys(obj).forEach(key => {
        let value = obj[key];
        let type = Object.prototype.toString.call(value).slice(8, -1);
        if (type === "Object") {
            deepClone(value);
        } else if (type === "Array") {
            newObj[key] = value.map(e => e);
        } else {
            newObj[key] = value;
        }
    })
    return newObj;
}

// 类型判断函数
function getValueType(value) {
    if (typeof value === null) {
        return "null";
    }
    let type = Object.prototype.toString.call(value).slice(8, -1);
    if (type === "Object") {
        return 'object'
    } else if (type === "Array") {
        return 'array'
    } else {
        return type
    }
}

// 订阅发布模式
function Listener() {
    this.listeners = {};
    this.add = function (type, fn) {
        this.listeners[type] = fn;
    }
    this.on = function (type) {
        if (this.listeners[type]) {
            this.listeners[type]()
        }
    }
    this.off = function (type) {
        if (this.listeners[type]) {
            delete this.listeners[type]
        }
    }
}
let listener = new Listener();
let fn = function () {
    console.log("click")
}
listener.add("click", fn)
listener.on("click")
listener.off("click")
listener.on("click")

// 数组去重
var arr = [1, 2, 3, 4, 4, 3, 2, 1];
function resetArr1(arr) {
    return Array.from(new Set(arr));
}
console.log(resetArr1(arr));
function resetArr2(arr) {
    let newArr = [];
    for (var i = 0; i < arr.length; i++) {
        if (newArr.indexOf(arr[i]) === -1) {
            newArr.push(arr[i])
        }
    }
    return newArr;
}
console.log(resetArr2(arr));

// 数组降维
// 1.递归
var arr = [1, 2, [3, 4, [5], 6], 7, [8]];
(function myFlat(arr) {
    var newArr = [];
    function flat(arr) {
        arr.forEach(item => {
            if (Array.isArray(item)) {
                flat(item)
            } else {
                newArr.push(item)
            }
        })

    }
    flat(arr);
    console.log(newArr)
    return newArr;
})(arr);
// 2.reduce
function myFlat2(arr) {
    return arr.reduce((prev, next) => prev.concat(Array.isArray(next) ? myFlat2(next) : [next]), [])
}
console.log(myFlat2(arr));

// new
function New(func) {
    var res = {};
    if (func.prototype !== null) {
        res.__proto__ = func.prototype;
    }
    var ret = func.apply(res, Array.prototype.slice.call(arguments, 1));
    if ((typeof ret === "object" || typeof ret === "function") && ret !== null) {
        return ret;
    }
    return res;
}


console 命令行工具 X clear

                    
>
console