call,apply,bind,new的模拟实现

看了微信公众号【前端大全】的文章,学习一下

        console.log("====================模拟call测试====================");
        //模拟call实现 apply的实现类似call  函数定义为function(context,arr)
        //1.改变this指向(第一个参数为null时,默认是window) 2.传入参数 返回结果 3.执行函数 
        Function.prototype.call2 = function(context){
            var context = context || window;
            context.fn = this; //把要执行的函数 作为context对象的方法执行  执行完再删除此方法

            var args = [];
            for(var i=1; i<arguments.length; i++){
              args.push('arguments[' + i + ']');

            }

            console.log(Array.isArray(arguments)); //false
            console.log(Array.isArray(Array.prototype.slice.call(arguments))); //true

            console.log("args: ");
            console.log(args);
            console.log(args.join(","));
            console.log(args.toString());
            console.log('context.fn(' + args + ')'); //context.fn(arguments[1],arguments[2])

            var result = eval('context.fn(' + args + ')'); //必须使用eval执行  才能将数组中的参数分开
            //var result = context.fn(args.join(","));//这种方式传进的参数是一个由args构成的一个字符串 无法正确执行

            delete context.fn; //执行完 删除

            return result;
        }

        //测试
        var value = 2;
        var obj = {
            value : 1
        };      
        function bar(name,age){
           console.log(this.value);
           return {
              value:this.value,
              name: name,
              age: age
           } 
        }

        console.log(bar.call2(null));
        //2 {age:undefined,name:undefined,value:2}

        console.log(bar.call2(obj,"kevin",18)); 
        //1 {age:undefined,name:undefined,value:1}

        console.log("====================模拟bind测试====================");
        //bind 模拟实现
        //1可以传入参数 2返回一个函数
        //当bind返回的函数作为构造函数的时候,bind时指定的this会失效 但传入的参数依然有效
        Function.prototype.bind2 = function(context){
            if(typeof this != "function"){
                throw new Error("what is trying to be bound is not a function");
            }

            var self = this;
            var args = Array.prototype.slice.call(arguments,1);
            var fNOP = function(){};//临时构造函数

            var fbound = function(){
                self.apply(this instanceof self?this:context, //判断是否是用【bind返回的构造函数生成的实例对象】.【方法】的形式调用
                    args.concat(Array.prototype.slice.call(arguments))

                    );
            }

            fNOP.prototype = this.prototype;
            fbound.prototype = new fNOP();

            return fbound;
        };      
        var value = 2;
        var foo = {
             value : 1
        };
        function bar(name,age){
            this.habit = 'shopping';
            console.log(this.value);
            console.log(name);
            console.log(age);
        }
        bar.prototype.friend = "kevin";
        var bindFoo = bar.bind2(foo,"daisy");

        var obj = new bindFoo("18");
        //undefined
        //daisy
        //18
        console.log(obj.habit);
        console.log(obj.friend);
        //shopping
        //kevin

        console.log("=====================模拟new测试=======================");
        //new 做的事情:(1)新建一个对象,对象原型是构造函数原型对象 (2)将参数传入构造函数中 执行 (3) 返回新建对象
        function objectFactory(){
            var obj = new Object();
            Constructor = [].shift.call(arguments); //取出第一个参数
            obj.__proto__ = Constructor.prototype;
            var ret = Constructor.apply(obj, arguments);
            return typeof ret == 'object'?ret:obj;
        }
        function Otaku(name,age){
            this.strength = 60;
            this.age = age;

            //若返回对象 则无法获取printProperties函数
            /*return {
                name:name,
                habit:"Games"
            };*/
        }
        Otaku.prototype.printProperties = function (){
            console.log("name: " + this.name + "; age: " 
                + this.age + "; strength: " + this.strength + "; habit: " + this.habit);
        };
        var testObj = objectFactory(Otaku,"Kevin","18");
        console.log(testObj);
         testObj.printProperties(); //name:undefined;age:18;strength:60;habit:undefined
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值