views:

469

answers:

3

I want to pass an object array to the setTimer function in Javascript.

setTimer("foo(object_array)",1000);

am getting error on this code.

Note:Sorry ! some correction in my question : Is it possible in setInterval() function.

+10  A: 

Use an anonymous function instead of a string on the first parameter of the setTimeout or setInterval functions:

// assuming that object_array is available on this scope
setInterval(function () { foo(object_array); }, 1000);

Why it works:

When you define an inner function, it can refer to the variables present in their outer enclosing function even after their parent functions have already terminated.

This language feature is called closures.

If you pass a string as the first argument of these functions, the code will be executed internally using a call to the eval function, and doing this is not considered as a good practice.

Eval provides direct access to the JavaScript compiler and executes the code it's passed with the privileges of the caller, also using eval repeatedly/extensively (i.e. your setInterval function is a good example) will lead to performance issues.

CMS
is it possible in setInterval()
coderex
Yes it's possble and that's the best way to do it
CMS
@CMS: it is working thanks :-)
coderex
+1  A: 

first, it's 'setTimeout'

second, don't pass a string. The real solution depends on the rest of the code. Most robust way would be to trap the scope:

var obj_array = something;
function trap(obj)
{
    function exec() { foo(obj); }
    return exec;
}
setTimeout(trap(obj_array), 1000);

trap returns a function that has your array trapped in its scope. This is a generic function but to make it specific to your problem, it can be simplified:

var obj_array = something;
function trap()
{
    function exec() { foo(obj_array); }
    return exec;
}
setTimeout(trap(), 1000);

or even:

var obj_array = something;
function trap()
{
    foo(obj_array);
}
setTimeout(trap, 1000);

and finally condensed down to:

var obj_array = something;
setTimeout(function() { foo(object_array); }, 1000);

EDIT: My functions (or at least 1 iteration of them I found in a backup here)

Function.prototype.createDelegate = function(inst, args) { 
    var me = this;
    var delegate = function() { me.apply(inst, arguments); }
    return args ? delegate.createAutoDelegate.apply(delegate,args) : delegate;
};
Function.prototype.createAutoDelegate = function() {
    var args = arguments;
var me = this;
return function() { me.apply({}, args); }
};

GIVEN:

function test(a, b) { alert(a + b); }

USAGE:

setTimeout(test.createAutoDelegate(1, 2), 1000);

OR GIVEN:

var o = { a:1, go : function(b) { alert(b + this.a); }}

USAGE:

setTimeout(o.go.createDelegate(o,[5]), 1000);
//or
setTimeout(o.go.createDelegate(o).createAutoDelegate(5), 1000);
Luke Schafer
+1  A: 

I'm going to expand on Luke's answer here because it addresses a use case that CMS's (and most answers to this kind of question) does not.

If you need to bind your arguments to the function call at the time you set the timeout, a simple function enclosure will not work:

echo = function (txt) { console.log(txt); };

val = "immediate A";
echo(val);

val = "delayed";
window.setTimeout(function () { echo(val); }, 1000);

val = "immediate B";
echo(val);

Assuming you are using Firebug's console, the above will output "immediate A", "immediate B" and then "immediate B" 1 second later. To bind the value at the time of the setTimeout call use Luke's trap method. The following modifies it a little to accept arbitrary functions and argument lengths:

echo = function (txt) { console.log(txt); };

trap = function (fn, args) {
    return function() {
        return fn.apply(this, args);
    };
};

val = "immediate A";
echo(val);

val = "delayed";
window.setTimeout( trap(echo, [val]), 1000);

val = "immediate B";
echo(val);

Not sure if there is a way to pass the caller's context in implicitly, but it could be further expanded to accept a context argument if "this" doesn't get you there.

Gin Doe
your version of trap is the same idea to my createDelegate and trapScope functions. Added to the bottom of my answer for interest
Luke Schafer
I've had to deal with this issue several times in the past and always settled for awkward state tracking workarounds until I saw your solution. Pretty much every topic I found about timeouts and intervals talked about using enclosures without considering race conditions.
Gin Doe