Skip to main content

function.bindenv(contextObject)

Clones the target function and binds it to a specified context object

Availability

Device + Agent

Parameters

Name Type Description
contextObject Object An alternative context object

Returns

Closure — a callable combination of function and state

Description

When any Squirrel function is called, it is passed a hidden parameter, this, which contains a reference to the object which ‘owns’ the function: the Global Table in the case of functions defined in the main body of a Squirrel program, or the instance of a class in the case of class methods.

If the called function uses a variable not declared local to that function, Squirrel will check whether its local to ‘outer’ functions in which the current function is nested, then the this object and finally the global table before reporting an error.

bindenv() allows you to specify an alternative object that will be passed into the function’s this parameter, to provide the function with access to variables declared in the passed object.

Because bindenv() clones the function and packages it with its of-the-moment data — together called a ‘closure’ — this method is used when you are providing callback functions, or you wish to alias a complex function with a simple variable name.

Combined with this, bindenv() also allows callbacks to be scheduled from within class definitions. In this case, this becomes a proxy for whatever instance happens to have called an imp API method to schedule the callback.

Note that bindenv() is applied to the function’s name, not an attempt to call that function. So:

imp.wakeup(5.0, doSomething.bindenv(myInstance));

will work, but:

imp.wakeup(5.0, doSomething().bindenv(myInstance));

will generate a Squirrel error. As such, bindenv() can’t be used with callback functions defined with one or more parameters when the callback function will not be invoked directly by your code. In the example above, doSomething() is called by impOS™ when the timer set by imp.wakeup() fires.

However, bindenv() can be used with parameter-defined functions when your code makes the call. If you pass a bound callback into, say, an object instance variable cb, you can add the callback’s parameters, err and data, at call time:

function receiveResponse(response) {
    foreach (index, request in _requests) {
        if (request.id == response.id) {
            if (response.err) {
                request.cb(response.err, null);
            } else if (response.data) {
                request.cb(null, response.data);
            }

            _requests.remove(index);
            break;
        }
    }
}

In the imp implementation of Squirrel, the function created by bindenv() holds a strong reference to its context object. This ensures the context object won’t be automatically disposed of by Squirrel’s memory manager before the function has been called. In standard Squirrel, the created function holds only a weak reference to its context object.

Further Information

For more detailed guidance on the role of context objects in Squirrel, please see Squirrel Closures And Context Objects.

Example Code

The following code uses bindenv() to set a callback's context object to reference a table holding information about an imp network interface. When the callback executes, we can access that table through the callback’s this context variable. This is useful here because otherwise the callback provides no information as to which interface was responsible for triggering the callback (only the interface’s new state value is passed into the callback code).