手写call,apply,bind功能

call、apply的实现原理

        function fn(x, y) {
            console.log('我想喝手磨咖啡' );
            console.log(this);
            console.log(x + y);
        }

        var obj={
            name :'andy'
        };
        
		//1、将函数设置为对象的属性
		obj.fn = fn
		//2、执行这个函数
		obj.fn()
		//3、删除添加的这个属性
		delete obj.fn

手写call方法

  • 方法一
        Function.prototype.newCall = function () {
        	//获取执行对象
            var tmp = arguments[0] || window;
            //获取函数的参数
            var args = [];
            for (var i = 1; i < arguments.length; i++) {
                args.push('arguments[' + i + ']');
            }
            //将函数设置为对象的属性
            tmp.fn = this;
            //使用eval方法执行函数,将函数的返回结果赋值给result
            var result = eval('tmp.fn(' + args.join(",") + ')');
            //删除为对象添加的fn属性
            delete tmp.fn;
            //返回返回结果
            return result;
        }

  • 方法二
        Function.prototype.mycall = function () {
            // 获取调用对象
            var tmp = arguments[0] || window;
            // 获取参数
            var args = [...arguments].slice(1)
            //将函数设置为对象的属性
            tmp.fn = this;
            //调用这个函数,将返回结果赋值给result
            var result = tmp.fn(...args)
            //删除为对象添加的fn属性
            delete tmp.fn;
            //返回函数的执行结果
            return result;
        }

手写apply方法

        Function.prototype.newApply = function () {
            // 获取函数的调用对象
            var tmp = arguments[0] || window;
            // 获取参数数组
            var args = arguments[1];
            //将函数设置为对象的属性
            tmp.fn = this;
            //将函数的执行结果返回给result
            var result = tmp.fn(...args);
            //删除新添加的属性
            delete tmp.fn;
            //返回执行结果
            return result;
        }

手写bind方法

        Function.prototype.newBind = function () {
            // 获取函数的调用对象
            var tmp = arguments[0] || window;
            // 获取参数
            var args = [...arguments].slice(1);
            //返回执行函数
            return () => {
            	//将函数设置为调用对象的属性
                tmp.fn = this;
                //调用这个函数,将返回值赋值给result
                var result = tmp.fn(...args);
                //删除新添加的属性
                delete tmp.fn;
                //返回结果
               	return result;
            }

        }

测试代码

        // 手写call方法
        // 法一
        Function.prototype.newCall = function () {
            var tmp = arguments[0] || window;
            var args = [];
            for (var i = 1; i < arguments.length; i++) {
                args.push('arguments[' + i + ']');
            }
            tmp.fn = this;
            var result = eval('tmp.fn(' + args.join(",") + ')');
            // eval('tmp.fn(' + args.join(",") + ')');
            delete tmp.fn;
            return result;
        }

        //方法二
        Function.prototype.mycall = function () {
            // 获取调用对象
            var tmp = arguments[0] || window;
            // 获取参数
            var args = [...arguments].slice(1)
            tmp.fn = this;
            var result = tmp.fn(...args)
            delete tmp.fn;
            return result;
        }
        
        // 手写apply
        Function.prototype.newApply = function () {
            // 获取函数的调用对象
            var tmp = arguments[0] || window;
            // 获取参数数组
            var args = arguments[1];
            tmp.fn = this;
            var result = tmp.fn(...args);
            delete tmp.fn;
            return result;
        }

        //手写bind
        Function.prototype.newBind = function () {
            // 获取函数的调用对象
            var tmp = arguments[0] || window;
            // 获取参数
            var args = [...arguments].slice(1);
            return () => {
                tmp.fn = this;
                var result = tmp.fn(...args);
                delete tmp.fn;
                return result;
            }

        }
        
        function fn(x, y) {
            console.log('我想喝手磨咖啡' );
            console.log(this);
            console.log(x + y);
            return {
                x:x,
                y:y,
            }
        }

        var obj={
            name :'andy'
        };
        console.log("-------------原理测试---------------");
        		//1、将函数设置为对象的属性
        		obj.fn = fn
        		//2、执行这个函数
        		obj.fn(1,2)
        		//3、删除添加的这个属性
                delete obj.fn
                console.log(obj);
        console.log("-------------原理测试---------------");
        console.log("-------------call-------------------");
        fn.call(obj,1,2)
        fn.newCall(obj,1,2)
        fn.mycall(obj,1,2)
        console.log(obj);
        console.log("-------------call-------------------");
        console.log("-------------apply------------------");
        fn.apply(obj,[1,2])
        fn.newApply(obj,[1,2])
        console.log(obj);
        console.log("-------------apply------------------");
        console.log("-------------bind-------------------");
        var a = fn.bind(obj,1,2)
        console.log(a());
        var b = fn.newBind(obj,1,2)
        console.log(b());
        console.log(obj); 
        console.log("-------------bind-------------------");

执行结果

-------------原理测试---------------
我想喝手磨咖啡
{name: "andy", fn: ƒ}
3
{name: "andy"}
-------------原理测试---------------
-------------call-------------------
我想喝手磨咖啡
{name: "andy"}
3
{x: 1, y: 2}
我想喝手磨咖啡
{name: "andy", fn: ƒ}
3
{x: 1, y: 2}
我想喝手磨咖啡
{name: "andy", fn: ƒ}
3
{x: 1, y: 2}
{name: "andy"}
-------------call-------------------
-------------apply------------------
我想喝手磨咖啡
{name: "andy"}
3
 {x: 1, y: 2}
我想喝手磨咖啡
{name: "andy", fn: ƒ}
3
 {x: 1, y: 2}
 {name: "andy"}
 -------------apply------------------
 -------------bind-------------------
我想喝手磨咖啡
{name: "andy"}
3
 {x: 1, y: 2}
我想喝手磨咖啡
{name: "andy", fn: ƒ}
3
 {x: 1, y: 2}
 {name: "andy"}
 -------------bind-------------------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值