最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Test if variable is a specific bound function in using javascript's Function.prototype.bind() - Stack Overflow

programmeradmin5浏览0评论

I am trying to work out how to test if a variable is an instance of a specific bound function. Consider the following example:

var func = function( arg ) {
    // code here
}

myFunc = func.bind( null, 'val' );

if( myFunc == func ) {
    console.log( true );
} else {
    console.log( false );
}

Unfortunately this results in false. Is there some sort of way of testing the variable to find out what function it is bound to?

I am trying to work out how to test if a variable is an instance of a specific bound function. Consider the following example:

var func = function( arg ) {
    // code here
}

myFunc = func.bind( null, 'val' );

if( myFunc == func ) {
    console.log( true );
} else {
    console.log( false );
}

Unfortunately this results in false. Is there some sort of way of testing the variable to find out what function it is bound to?

Share Improve this question asked Apr 23, 2015 at 0:34 McShamanMcShaman 4,0258 gold badges39 silver badges48 bronze badges
Add a ment  | 

5 Answers 5

Reset to default 7

No, there is not a way to do this. .bind() returns a new function that internally calls the original one. There is no interface on that new function to retrieve the original one.

Per the ECMAScript specification 15.3.4.5, the returned "bound" function will have internal properties for [[TargetFunction]], [[BoundThis]] and [[BoundArgs]], but those properties are not public.

If you tell us what higher level problem you're trying to solve, we might be able to e up with a different type of solution.


If you yourself control the .bind() operation, you could put the original function on the bound function as a property and you could test that property:

var func = function( arg ) {
    // code here
}

myFunc = func.bind( null, 'val' );
myFunc.origFn = func;

if( myFunc === func || myFunc.origFn === func) {
    console.log( true );
} else {
    console.log( false );
}

Demo: http://jsfiddle/jfriend00/e2gq6n8y/

You could even make your own .bind() replacement that did this automatically.

function bind2(fn) {
    // make copy of args and remove the fn argument
    var args = Array.prototype.slice.call(arguments, 1);
    var b = fn.bind.apply(fn, args);
    b.origFn = fn;
    return b;
}

You can't do this directly because functions, just like Objects, have their equality tested by their reference which no longer matches, §11.9.3, point 1. f. or §11.9.6, point 7.

However, you could create some custom properties to test for, e.g.

function myBind(fn) { // takes 2+ args, the fn to bind, the new this, any other args
    var bind = Function.prototype.bind,
        bound = bind.call.apply(bind, arguments);
    bound.unbound = fn;
    return bound;
}

and then examle usage

function foo(bar) {
    console.log(this, bar);
}

// binding
var fizz = myBind(foo, {buzz:0}, 'baz');
fizz(); // logs {buzz: 0} "baz"

// testing
fizz.unbound === foo; // true

If you want to test in both directions, then you will need to OR them together, and perhaps even consider looping over these properties if you will be binding already bound functions

fizz.unbound === foo || fizz === foo.unbound; // true

Please also consider that the whole chain of unbound versions of the function will not be released from memory as long as a bound version exists, whereas some browsers would have been able to free this memory, depending on their implementation of bind

Bind prepend "bound " before the source function's name.

If you can give a explicite name to the source function then you can do :

var func = function func( arg ) {
    // code here
}

var myFunc = func.bind( null, 'val' );


if( myFunc.name.match(/^(bound\ )*(.*)$/i)[2] === func.name ){

        console.log(true);

}

Thanks for your input @jfriend00 and @PaulS. I am using a function that automatically adds an unbound property to the bound function. Here is a refined version of what I wrote. Let me know what you think.

// My function
var myFunc = function() {
    return 'This is my function';
};

// Function I'm wrapping my function in
var wrapper = function( fn ) {

    var result;

    if( fn ) {
        result = fn.apply( null, arguments );
    }

    // Any additional logic I want to run after my function
    console.log( 'Ran wrapper logic' );

    return result;

};

// Modified binder method
var binder = function( fn, ths, args ) {

    args = [].concat( ths, args );

    var bound = fn.bind.apply( fn, args );

    bound.unbound = fn;

    return bound;

};

// Bind a wrapped version of my function 
myFunc = binder( wrapper, null, myFunc );

// I can test if my function has ben wrapped
console.log( myFunc.unbound == wrapper );

// And I can run a wrapped version of my function
console.log( myFunc() );

You can use the instanceof operator as long as your bound function is a constructable function and the variable you are testing is an instance of your constructable.

From MDN:

When using a bound function as the right-hand side of instanceof, instanceof would reach for the target function (which is stored internally in the bound function) and read its prototype instead.

var func = function( arg ) {
    // code here
}

myFunc = func.bind( null, 'val' );

if( new func instanceof myFunc ) {
    console.log( true );
} else {
    console.log( false );
}

You simply have to write func so that it doesn't do anything unwanted when creating a new instance of it. For example if func doesn't need to construct:

var func = function( arg ) {
    if (this instanceof func) return;// do nothing
    // code here
}
发布评论

评论列表(0)

  1. 暂无评论