SOURCE

// 1.手写 Object.create()
function myCreate(obj) {
    function f() {}
    f.prototype = obj;
    return new f();
}

// 2.手写 instanceof 方法
function myInstanceof(obj, f) {
    let proto = Object.getPrototypeOf(obj);
    let prototype = f.prototype;
    while (proto) {
        if (proto == prototype) return true;
        proto = Object.getPrototypeOf(proto);
    }
    return false;
}
// var obj = [];
// console.log(myInstanceof(obj, Array));

// 3.手写 new 操作符
function myNew() {
    let obj = null;
    let constructor = Array.prototype.shift.apply(arguments);
    if (typeof constructor !== 'function') {
        throw Error('参数类型错误');
        return;
    }
    obj = Object.create(constructor.prototype);
    let result = constructor.apply(obj, arguments);
    let flag = result && (typeof result === 'object' || typeof result === 'function');
    return flag ? result : obj;
}

// 4.手写promise

// 5.手写promise.then

// 6.手写promise.all

// 7.手写promise.race

// 8.手写防抖函数
function debounce(fn, wait) {
    let timer = null;
    return function() {
        let context = this;
        let args = arguments;

        if (timer) {
            clearTimeout(timer);
            timer = null
        }

        timer = setTimeout(() => {
            fn.apply(context, args)
        }, wait)
    }
}

// 9.手写节流函数
function throttle(fn, wait) {
    let previous = 0
    return function(...args) {
        let now = +new Date();
        if (now - previous > wait) {
            previous = now;
            fn.apply(this, args)
        }
    }
}
// const betterFn = throttle(() => { //先执行throttle函数,创建previous变量,把previous留在内存中;此时betterFn就是throttle返回的函数
//     console.log('fn 函数执行了')
// }, 1000)
// setInterval(betterFn, 10)


// 10.手写类型判断函数
function getType(value) {
    if (value === null) {
        return value + ''
    }

    if (typeof value === 'object') {
        return Object.prototype.toString.apply(value).slice(8, -1);
    } else {
        return typeof(value)
    }
}
// let obj = []
// console.log(getType(obj));

// 11.手写 call 函数
Function.prototype.myCall = function(context) {
    if (typeof this !== 'function') {
        throw Error('调用类型错误');
    }
    let args = [...arguments].slice(1)
    context = context || window;
    context.fn = this;
    let result = context.fn(...args);
    delete context.fn;
    return result;
}

// 12.手写apply函数
Function.prototype.myApply = function(context) {
    if (typeof this !== 'function') {
        throw Error('调用类型错误');
    }
    let args = arguments[1],
        result = null;
    context = context || window;
    context.fn = this;
    if (args) {
        result = context.fn(...args);
    } else {
        result = context.fn();
    }
    delete context.fn;
    return result;
}

// 12.手写bind函数
Function.prototype.myBind = function(context) {
    if (typeof this !== 'function') {
        throw Error('调用类型错误');
    }
    context = context || window;
    let fn = this;
    let args = [...arguments].slice(1);
    return function() {
        return fn.apply(this instanceof fn ? this : context, args.concat(...arguments))
    }
}

// 13.函数柯里化
function currying(fn, ...args) {
    let len = fn.length;
    return function(...params) {
        let _args = [...args, ...params];
        if (_args.length < len) {
            return currying.call(this, fn, ..._args);
        } else {
            return fn.apply(this, _args)
        }
    }
}

// 14.实现AJAX请求
// const server_url = '/server';
// // let xhr = new XMLHttpRequest();
// xhr.open('GET', server_url, true);
// xhr.onreadystatechange(function() {
//     if (this.readyState !== '4') return;
//     if (this.status == '200') {
//         return this.response
//     } else {
//         console.log(this.statusText)
//     }
// })
// xhr.responseType = 'json';
// xhr.setRequestHeader('Accept', 'application/json');
// xhr.send(null);

// 15.promise封装AJAX请求
// function getJson(url) {
//     let promise = new Promise((resolve, reject) => {
//         let xhr = new XMLHttpRequest();
//         xhr.open('GET', url, true);
//         xhr.onreadystatechange(function() {
//             if (this.readyState !== '4') return;
//             if (this.status === '200') {
//                 resolve(this.response)
//             } else {
//                 reject(new Error(this.statusText))
//             }
//         })
//         xhr.responseType = 'json';
//         xhr.setRequestHeader('Accept', 'application/json');
//         xhr.send(null);
//     })
//     return promise;
// }

// 16.实现浅拷贝
//(1)Object.assign
// (2)扩展运算符
// (3)数组方法:Array.prototype.slice, Array.prototype.concat
// (4)手写浅拷贝
function shallowCopy(obj) {
    let newObj = {};
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            newObj[key] = obj[key];
        }
    }
    return newObj;
}

// 17.实现深拷贝
// (1)JSON.stringify()
// (2)函数库lodash的_.cloneDeep方法
// (3)手写深拷贝
function deepCopy(obj) {
    let newObj = Array.isArray(obj) ? [] : {};
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
        }
    }
    return newObj;
}
console 命令行工具 X clear

                    
>
console