js中bind函数的实现

bind函数的主要目的,是改变函数执行时this的指向,也就是函数执行环境的上下文。

小插曲:什么是方法?当对象的属性是一个函数时,我们称之为对象的一个方法。为什么修改this指向?因为方法内部的函数,this默认会指向全局window,为什么会这样呢?因为语言缺陷!还有,原型prototype是一个对象,一个对象,对象,象…想起了曾经写过的

 B = function(){...};
 //无知者无畏啊!
 a.prototype = B;//错
 a.prototype = new B();//对

简单修改函数this指向,我们可以像下面一样给目标函数绑定作用域:

Function.prototype.bind = function(context){
            //将调用bind的目标函数的this保存起来
            var self = this;

            return function(){
                return self.apply(context,arguments);
            }
        }

考虑到函数柯里化,支持bind在绑定对象时传递参数:

Function.prototype.bind = function(context){
            //将调用bind的目标函数的this保存起来
            var self = this,
                args = Array.prototype.slice.call(arguments,1);//eg:foo.bind(obj,1)
            return function(){
                var innerArgs = Array.prototype.slice.call(arguments);
                var finalArgs = args.concat(innerArgs);
                return self.apply(context,finalArgs);
            }
        }

现在实现了this指向的绑定,我们需要做的是让返回的函数能够继承self原有的属性,即原型链的继承:

Function.prototype.bind = function(context) {
        //将调用bind的目标函数的this保存起来
        var self = this,
            FNop = function() {},
            args = Array.prototype.slice.call(arguments, 1), //eg:foo.bind(obj,1)
            bound = function() {
                var innerArgs = Array.prototype.slice.call(arguments);
                var finalArgs = args.concat(innerArgs);
                return self.apply(context, finalArgs);
            };
            //使用空转函数FNop继承self的原型对象,再将返回函数的原型作为空转函数的实例,这样在修改bound.prototype属性时就不会更改self.prototype属性了,这也是不使用bound.prototype = self.prototype的意义所在
            FNop.prototype = self.prototype;
            bound.prototype = new FNop();
            return bound;
    }

最后为了浏览器能够支持bind,毕竟bind是ES5才有的prototype方法,我们只需要小小修改即可,主要是对调用bind的目标不是函数是作出提示,这也是原生JS实现bind的方法:

 Function.prototype.bind = function(context) {
        //判断调用bind的目标是否为函数
        if (typeof this !== "function") {
            throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
        }
        //将调用bind的目标函数的this保存起来
        var self = this,
            FNop = function() {},
            args = Array.prototype.slice.call(arguments, 1), //eg:foo.bind(obj,1)
            bound = function() {
                return self.apply(this instanceof FNOP && context ? this : context || window,
                    args.concat(Array.prototype.slice.call(arguments)));
            };
        //使用空转函数FNop继承self的原型,再将返回函数的原型作为空转函数的实例,这样在修改bound.prototype属性时就不会更改self.prototype属性了,这也是不使用bound.prototype = self.prototype的意义所在
        FNop.prototype = self.prototype;
        bound.prototype = new FNop();
        return bound;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值