call,apply和bind的区别

相同点:在特定的作用域中调用函数均能改变this的指向;
不同点:call和apply除了传参方式不同其他的作用是完全相同的,call的传参方式是散列的,apply则是传一个数组,且使用call和apply后函数会立即执行,而bind则返回一个新的函数等待被调用。
在这里稍微仿写以下这三个的实现方法:
call和apply:

        var name = 'window';
        function show(name,age){
            this.name = name;
            this.age = age
            console.log(this,this.name,this.age);
            return this.name + this.age;
        }  
        var obj = {
            name: 'obj',
            age: 18
        }  
        show('window',18) //window 'window' 18
        show.call(obj,'call',30) //obj 'call' 30
        show.apply(obj,['apply',18]) //obj 'apply' 18

        Function.prototype.myCall = function(target){
            var args = Array.prototype.slice.call(arguments,1);
            var arr = [];
            for(var i = 0; i < args.length; i++){
                arr.push('args['+i+']');
            }
            target.fn = this;
            var result = eval('target.fn('+ arr.join(",") +')');
            delete target.fn;
            return result;
        }
        show.myCall(obj,'myCall',30);//obj 'myCall' 30
        
        Function.prototype.myApply = function(target){
            var args = arguments[1];
            var arr = [];
            for(var i = 0; i < args.length; i++){
                arr.push('args['+i+']');
            }

            target.fn = this;
            var result = eval('target.fn('+ arr +')');
            delete target.fn;
            return result;
        }
        show.myApply(obj,['myApply',18]); //obj "myApply" 18

bind:

        var name = 1;
        Father.prototype.lastName = 'dn';
        function Father(){

        }
        fn.prototype = new Father();
        function fn(name,age){
           this.name = name;
            this.age = age;
            console.log(this,this.name,age,this.lastName);
        }
        obj = {
            name:'xx'
        }
        fn('ll',22);  
        //this-->window 'll' 22 undefined

        fn.call(obj,'liu',18); 
        //this--> obj{name:'liu',age:18} 'liu' 18 undefined
        
        var newFn = fn.bind(obj);
        newFn('zhang',19);      
        //this --> obj{name:'zhang',age:19} 'zhang' 19 undefined
        
        var newFb = fn.bind(obj,'xu');
        newFb(20);     
        //this --> obj{name:'xu',age:20} 'xu' 20 undefined
        
        var newb = newFn.bind(window);
        newb('lei',22);   
        //bind --> 只能进行一次改变this指向,后面无用
        //this ---> obj{name:'lei',age:22} 'lei' 22 undefined

        new newFn('new',5); 
        //this ---> fn的对象{name:'new',age:5} 'new' 5 'dn'  改变了bind的this

        Function.prototype.myBind = function(target){
            var target = target || window;
            var args = Array.prototype.slice.call(arguments,1);
            // console.log(args)
            var self = this;
            var temp = function(){};
            var F = function(){
                // console.log(this)
                var arg = args.concat(Array.prototype.slice.call(arguments,0));
                // console.log(arg)
                return self.apply(this instanceof temp? this : target,arg);
            }
            
            temp.prototype = self.prototype;
            F.prototype = new temp();
            return F;
        }
        var fnMyBind = fn.myBind(obj,'mybind');
        fnMyBind(18)
        // this ---> obj{name:'mybind':age:18} 'mybind' 18 undefined;

        var fnBindBind = fnMyBind.myBind(window)
        fnBindBind(666);
        // this ---> obj{name:'mybind':age:666} 'mybind' 666 undefined;

        new fnMyBind(99);  
        //this --->fn的对象{name:'mybind',age:99} 'mybind' 99 'dn'
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值