ECMAScript扩展 -9 【重写bind方法】

一.重写bind方法

bind定义与call区别

p1.play.call(p2, '男'); // call会改变this指向并立即执行
p1.play.bind(p2, ['男', 20]); //bind会改变this指向后返回一个新的函数,不执行

bind挂载在Function.prototype上

无参的重写

Function.prototype.bindy = function(context){
    var _self = this;
    return function(){
        _self.apply(context);
    }
}

在写一个匿名函数是因为要求不执行,其次保存this是因为匿名函数的中的this指向的是window

有参数的重写

Function.prototype.bindy = function(context){
    var _self = this,
        args = Array.prototype.slice.call(arguments, 1);
    return function(){
        var newArgs = Array.prototype.slice.call(arguments);
        _self.apply(context, args.concat(newArgs));
    } 
}

利用slice的方法截取arguments的第二位以后的形参。通过contcat连接两种方式的传值

Person.bindy(p, 'zza')('zzb');

你在直接调用的时候是需要排除第一个参数的

有参数要考虑三种情况,第一种是在调用的时候传参,第二种是在执行的时候传参,第三种是都传。

实例化构造函数的重写

var p ={
    age: 20
}
function Person(name,sex){
    console.log(this.age);
    console.log(name, sex);
}
Function.prototype.bindy = function(context){
    var _self = this,
        args = Array.prototype.slice.call(arguments, 1);
    var fn = function(){
        var newArg = Array.prototype.slice.call(arguments);
        _self.apply(this instanceof _self ? this : context, args.concat(newArg))
    }
    fn.prototype = this.prototype;
    return fn;    
}
var ar = Person.bindy(p, '张三');
new ar('15');

将返回的匿名函数赋值给一个变量,这时候再将变量的原型指向为调用函数的属性的原型。这时候判断如果当前的作用域是由当前调用函数的属性创建的,则将this指向为调用函数的属性(实例化对象),如果不是,则照常处理。

其中fn.prototype = this.prototype;的作用:

实例化后this无论如何都是指向实例化对象的。但是constructor是不同的,不赋值原型的话构造器是指向fn的,这样就会导致判断失效一直为false。

所以将fn的原型改为当前调用函数的属性的原型,这样就可以让判断生效了,如果为实例化的对象,在instanceof中this指向的是实例化对象,constructor却为Person.没有实例化的,则this直接指向window。

圣杯模式解决原型属性变更问题

Function.prototype.bindy = function(context){
    var _self = this,
        args = Array.prototype.slice.call(arguments, 1),
        tempFn = function(){},
     fn = function(){
        var newArg = Array.prototype.slice.call(arguments);
        _self.apply(this instanceof _self ? this : context, args.concat(newArg))
    }
    tempFn.prototype = this.prototype;
    fn.prototype = new tempFn();
    return fn;    
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值