【学记】call、apply、bind方法、new运算符的原理解析和手写

115 阅读2分钟

手写call

call的核心是改变了函数的this指向,最简单的实现方法,就是把要执行的函数作为要call的目标的方式使用,上代码

//这里不能用箭头函数哦,因为箭头函数没有this,会导致错误
Function.prototype.myCall = function(thisArg, ...args) {
    //thisArg是要改变this指向的目标
    //this指向调用myCall的函数
    const func = this
    if (typeof thisArg === "undefined" || thisArg === null) {
        //thisArg是null或者undefined直接执行func
        func(...args)
        return false;
    }
    //将函数作为thisArg的方法
    thisArg.func = func
        //接受func的返回值
    const result = thisArg.func(...args)
        //删掉func方法
    delete thisArg.func
    return result
}

但是这里还是有一点小问题,如果thisArg.func本来就存在呢,那么在我们给func属性赋值时,会把原有的值覆盖掉,所以利用原始数据类型Symbol(Symbol表示独一无二的值,最大的用法是用来定义对象的唯一属性名)来解决这个问题

//这里不能用箭头函数哦,因为箭头函数没有this,会导致错误
Function.prototype.myCall = function(thisArg, ...args) {
    //thisArg是要改变this指向的目标
    //this指向调用myCall的函数
    const func = this
    if (typeof thisArg === "undefined" || thisArg === null) {
        //thisArg是null或者undefined直接执行func
        func(...args)
        return false;
    }
    //我symbol是独一无二哒
    const func = Symbol['func'];
    //将函数作为thisArg的方法
    thisArg[func] = func;
        //接受func的返回值
    const result = thisArg[func](...args)
        //删掉func方法
    delete thisArg[func]
    return result
}

手写apply

apply很简单,就把形参改改就行了

Function.prototype.myApply = function(thisArg, args) {
    ......
}

手写bind

bind方法返回的是一个函数,可以再传参

Function.prototype.myBind = function(thisArg, ...args) {
    const func = this;
    const reFunc = function(...args1) {
        args = [...args, ...args1];
        func.myCall(thisArg, ...args);
    };
    return reFunc;
}

手写new

new是运算符,所以这里只是采用函数的方式实现new的功能,先分析一下new的具体作用

  1. 创建一个新对象,并让这个对象的__proto__指向构造函数的prototype原型对象
  2. 执行构造函数,并让其this指向对象
  3. 根据构造函数return的值决定最终返回的值,这里不多说,后面代码再细说
const myNew = (func,...arg)=>{
    //创建一个新对象,让其__proto__等于构造函数的原型对象prototype
    const obj = Object.create(func.prototype)
    //执行构造函数func,并让其this指向obj
    const result = func.call(obj,...arg)
    const isFunOrObj = (typeof result !==null&&typeof result ==="object")||typeof result==="function"
    //如果构造函数return了object和function,则直接返回这这个值否则返回实例对象
    return isFunOrObj?result:obj
}