手写call/apply/bind/new

225 阅读1分钟

call()

call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。 参考 developer.mozilla.org/zh-CN/docs/…

function.call(thisArg, arg1, arg2, ...)

        Function.prototype.myCall = function(target, ...args) {
            if (typeof this !== "function") {
                throw new TypeError("not a function")
            }
            console.log(target)
            target = target || window
            console.log(this)   // this 指向调用 myCall函数的对象
            target.fn = this    // 隐式绑定,改变构造函数的调用者,间接改变 this 指向
            let result = target.fn(...args)
            return result
        };

        function Product(name, price) {
            this.name = name;
            this.price = price;
        }

        function Food(name, price) {
            Product.myCall(this, name, price);
            this.category = 'food';
        }

        console.log(new Food('cheese', 5).name);

image.png

apply()

apply() 方法调用一个具有给定this值的函数,以及以一个数组(或类数组对象)的形式提供的参数。 参考developer.mozilla.org/zh-CN/docs/…

func.apply(thisArg, [argsArray])

 Function.prototype.myApply = function(target) {
            if (typeof this !== "function") {
                throw new TypeError("not a function");
            }
            if (!Array.isArray(arguments[1])) {
                throw new Error('arg not a array')
            }
            target = target || window
            target.fn = this
            let args = arguments[1];
            let result = target.fn(args)
            return result
        }
        const obj = {
            name: 'sandwich'
        };
        function fun(...args) {
            console.log(this.name)    // sandwich
            console.log(args)         // ['lurenjia']
        }
        fun.prototype.name = 'jack';
        const arr = ['lurenjia']
        fun.myApply(obj, arr);

bind()

bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。

参考:developer.mozilla.org/zh-CN/docs/…

function.bind(thisArg[, arg1[, arg2[, ...]]])

     Function.prototype.myBind = function(context){
           if (typeof this !== 'function') {
               throw TypeError("Bind must be called on a function");
            }
            let self = this;              //保存this
            let argu = [...arguments].slice(1)   //支持柯里化传参,保存参数
            //返回一个绑定this的函数
            return function(){
                let newArgu = [...arguments]
                return self.apply(context,argu.concat(newArgu))
            }
        }
        const obj = {
            name: 'sandwich'
        };
        function fun() {
            console.log(this.name)
        }
        fun.prototype.name = 'jack';
        let test = fun.myBind(obj)
        test()    //调用输出sandwich

new()

new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。

参考:developer.mozilla.org/zh-CN/docs/…

new constructor[([arguments])]

      //简单实现
        function myNew(func, ...argus) {
            let tempObj = {};
            func.apply(tempObj, argus)
            return tempObj
        }

        let Foo = function(name, age) {
            this.name = name;
            this.age = age
        }
        let foo = myNew(Foo, 'jiangyao', 21)
        console.log(foo.name)   //jiangyao