Bind is transient

Test code

Here’s the test code for attribute bind.

TEST('transient-bind', function()
{
    // Set up the test object.
    var return_this = function(){
        return this;
    };
    var obj = {
        return_this : return_this
    };
    assert( obj.return_this === return_this );

    // Deferring method call changes the outcome.
    var method_deferred = obj.return_this;
    assert( method_deferred ===  obj.return_this );
    assert( method_deferred() !==  obj.return_this() );  // AAA

    // The two outcomes, precisely stated.
    assert( obj.return_this() === obj );
    assert( method_deferred().telltail === 'global' );

    // Another view on the matter.
    assert( method_deferred === return_this );
    assert( method_deferred() === return_this() );  // BBB

});

Discussion

We create an object that has a return_this method. The outcome of calling return_this depends on how it is called.

There’s a logic in the test code that produces contradictory, or at least surprising, outcomes.

From

we would expect

But this means that in obj.return_this() the obj is not relevant. But JavaScript (or its designers) wanted objects to have methods, so they introduced a special rule.

Explanation

JavaScript does not distinguish classes and instances. Python, and perhaps other dynamic languages, does. This allows Python to supply a bound method, which retains a reference to the object, when a function belonging to the class is called on an instance.

Here’s a Python (version 3) command line dialogue that illustrates this.

>>> def method(): pass          # The function.
...
>>> class A: method = method    # The class.
>>> A.method                    # Function from class.
<function method at 0x15be518>
>>> A.method is method          # Same as the original function.
True
>>> a = A()                     # Instance.
>>> a.method                    # Bound method, not original function.
<bound method A.method of <__main__.A object at 0x16b9d10>>

The odd behaviour shown in the JavaScript test code is a consequence of JavaScript not distinguishing between classes and instances.