首页 > 亚博pt平台 > Hardbinding&SoftbindingdetailedexplanationinJS

Hardbinding&SoftbindingdetailedexplanationinJS

2019-09-14

JavaScript中硬绑定与软绑定详解

JS中硬绑定这种方式可以把this强制绑定到指定的对象(除了使用new时),防止函数调用时应用默认绑定规则(非严格模式下全局对象-window
| global,严格模式下undefined)。硬绑定会大大降低函数的灵活性,使用硬绑定之后就无法使用像“隐式绑定”或“显示绑定”来修改this。

如果可以给默认绑定指定一个全局对象和undefined意外的值,那就可以实现和“硬绑定”相同的效果,同时保留“隐式绑定”或“显示绑定”修改this的能力。

// hard binding
if(!Function.prototype._hardBind) {
    Function.prototype._hardBind = function(oThis) {
        if(typeof this !== 'function') {
            throw new TypeError('Function.prototype.softBind - what is trying to be bound is not callable.');
        }
        var aArgs = [].slice.call(arguments, 1);
        var fToBind = this;
        var fNOP = function() {};
        var fToBound = function() {
            return fToBind.apply(this instanceof fNOP ? this : oThis, aArgs.concat([].slice.call(arguments)));
        };
        if(this.prototype) {
            fNOP.prototype = this.prototype;
        }
        fToBond.prototype = new fNOP();
        return fToBond;
    };
}


// test code
function foo() {
    console.log('name: ' + this.name);
}

var obj1 = {name: 'obj1'};
var obj2 = {name: 'obj2'};
var obj3 = {name: 'obj3'};

var _foo = foo._hardBind(obj1);
_foo(); // 'name: obj1'

obj2.foo = foo._hardBind(obj1);
obj2.foo(); // 'name: obj1'

_foo.call(obj3); // 'name: 'obj1'

setTimeout(obj2.foo, 100); // 'name: obj1'


// soft binding
if(!Function.prototype._softBind) {
    Function.prototype._softBind = function(oThis) {
        if(typeof this !== 'function') {
            throw new TypeError('Function.prototype.softBind - what is trying to be bound is not callable.');
        }
        var aArgs = [].slice.call(arguments, 1);
        var fToBind = this;
        var fToBound = function() {
            return fToBind.apply((!this || (this === (window || global))) ? oThis : this, aArgs.concat([].slice.call(arguments)));
        };
        fToBound.prototype = Object.create(fToBind.prototype);
        return fToBound;
    };
}


// test code

function foo() {
    console.log('name: ' + this.name);
}

var obj1 = {name: 'obj1'};
var obj2 = {name: 'obj2'};
var obj3 = {name: 'obj3'};

var _foo = foo._softBind(obj1);
_foo(); // 'name: obj1'

obj2.foo = foo._softBind(obj1);
obj2.foo(); // 'name: obj2'

_foo.call(obj3); // 'name: obj3'

setTimeout(obj2.foo, 100); // 'name: obj1' 


可以看到,软绑定版本的foo()可以手动将this绑定到obj2或者obj3上,但如果应用默认绑定规则,则会将this绑定到oThis。

参考:You Dont Known JS

原文链接:https://segmentfault.com/a/1190000016026397

文章标签: