How do I send a condition test to a Javascript function and not only it's result?
I had the idea about making a small jQuery plugin but there's something I don't know how to do it without having to rely on eval
.
Here's the code:
var testMe = 1;
$.extend({
once : function( condition, duration, callback) {
window[ "once" ] = window.setTimeout(function() {
if ( condition )
{
callback.apply();
window.clearTimeout( window[ "once" ] );
} else {
window[ "once" ] = window.setTimeout( arguments.callee, duration * 1000 );
}
}, duration * 1000 );
}
开发者_JAVA技巧});
$.once(testMe == 2, 5, function() {
alert("Match!");
});
It looks like when $.once()
is being called, the first parameter is then evaluated and only it's value at this time is sent to the condition parameter. The only way I found is to send it as a string:
$.once("testMe == 2" ...
and use if ( eval( condition ) )
Is there another way withing the use of eval
?
Thank you.
Edit: here is the a final version of the plugin:
var testOne = 1,
testTwo = 1;
$.extend({
once : function( name, conditionFn, duration, callback) {
if ( typeof duration == "function" )
{
callback = duration;
duration = 5;
}
window[ "once" + name ] = window.setInterval(function() {
if ( conditionFn() )
{
callback();
window.clearInterval( window[ "once" + name ] );
}
}, duration * 1000 );
}
});
//Examples
$.once("testOne", function() {
return testOne == 2
}, 2, function() {
alert("testOne == 1");
});
$.once("testTwo", function() {
return testTwo == 2
}, 2, function() {
alert("testTwo == 1");
});
You are correct; the parameters are evaluated and then passed. I would not recommend using eval
unless you really know what you're doing, and there's a compelling reason to do so.
Instead, pass a predicate (a function which returns a boolean) to your plugin. Every time you want to do the check, invoke the function:
var testMe = 1;
$.extend({
once : function(predicate, duration, callback) {
window.once = window.setInterval(function() {
if (predicate()) {
window.clearInterval(window.once);
callback();
}
}, duration * 1000);
}
});
$.once(function () { return testMe == 2; }, 5, function() {
alert("Match!");
});
N.B. I replaced your repeated setTimeout
calls with a self-cancelling setInterval()
. Also, you were invoking the callback
with callback.apply()
, but there is no reason to do this. You can directly call it with ()
, as the above code does.
Send a function that returns the result of the comparison:
var testMe = 1;
$.extend({
// receive the function
once : function( conditionFn, duration, callback) {
window[ "once" ] = window.setTimeout(function() {
// execute the function
if ( conditionFn() )
{
callback.apply();
window.clearTimeout( window[ "once" ] );
} else {
window[ "once" ] = window.setTimeout( arguments.callee, duration * 1000 );
}
}, duration * 1000 );
}
});
// send a function
$.once(function(){return testMe == 2;}, 5, function() {
alert("Match!");
});
精彩评论