SOURCE

/**
 * 函数柯里化:将接收多个参数的函数变为每次接收单一参数的函数并返回能继续接收余下参数的新函数
 */
function curry(fn) {
    // 返回值无疑是个函数
    return function curried() {
        //console.log(arguments)
        // arguments是伪数组,类似用for...in打印出Array的格式
        const args = Array.from(arguments)
        if(args.length>=fn.length) {
            // args.length是实参
            // fn.length是形参
            return fn.apply(this, args)
        }else {
            // 为了获取后续的参数
            return function() {
                // console.log(arguments)
                // 这里的递归非常重要
                return curried.apply(this, args.concat(Array.from(arguments)))
            }
        }
    }
}

function add(a,b,c) {
    return a+b+c
}

const curriedAdd = curry(add)
console.log(curriedAdd(1)(2)(3))

/**
 * 手写bind
 */
Function.prototype.myBind = function() {
    const args = Array.from(arguments)
    const thisArg = args.shift();
    const self = this;
    // bind的返回值肯定是个函数
    return function() {
        return self.apply(thisArg, args)
    }
}

function fn1(a, b, c) {
    console.log('this', this)
    console.log(a, b, c)
    return 'this is fn1'
}

const fn2 = fn1.myBind({x: 100}, 10, 20, 30)
const res = fn2()
console.log(res)

/**
 * 手写new
 */
function myNew(obj, ...rest) {
    // 链接原型
    const newObj = Object.create(obj)
    // 绑定this
    const result = obj.apply(newObj, rest)
    // 判断返回值
    return typeof result === 'object' ? result : newObj;
}

function Person(firtName, lastName) {
  this.firtName = firtName;
  this.lastName = lastName;
}

const tb = new Person('Chen', 'Tianbao');
console.log(tb);

const tb2 = myNew(Person, 'Chen', 'Tianbao');
console.log(tb2)
console 命令行工具 X clear

                    
>
console