Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use recursion instead of EVAL

I have a list of items in a page that must be hidden in sequence, but just after the previous item has been totally hidden.

I made the following code, where I create a big string inserting the callbacks inside the previous callbacks and later use eval to execute the effects, but despite the code is working fine as expected, I'm totally sure that's not the best way to do this.

// get items to hide
    var itemsToHide = jQuery(".hide");

// function responsible to hide the item
    var hideItem = function (item, callback) {
     jQuery(item).hide(100, callback)
    };

// declare an empty function, to be the first to be called
    var buff = function(){};

    for (var i = 0; i < itemsToHide.length; i++) {
// put the previous value of buff in the callback and assign this to buff
     buff = "function(){hideItem(itemsToHide[" + i + "], " + buff + ");}";
    }

// execute the effects
    eval("(" + buff + ")()");

Any suggestion on how to accomplish this effect using recursion, without the "evil" eval?

like image 295
n33x Avatar asked Jun 10 '26 04:06

n33x


1 Answers

Hiding with recursion - functional style

In this case you know the duration of the effect, so you can do as others suggested.

However you might still want to know how to achieve the same using a more functional style, using a simple recursion.

So here I show you a way to do that.

1. The code

<script src="http://code.jquery.com/jquery-latest.pack.js"></script>
<script type="text/javascript">
    $(function() {
        var items = jQuery(".to-hide");
        (function hideRec() {
            if (items.length == 0) {
                window.alert("The end.");
                return;
            }
            var toHide = jQuery(items[0]);
            items = items.slice(1);
            toHide.hide("100", hideRec);
        })();
    });
<script>

<ul>
    <li class="to-hide">...</li>
    <li class="to-hide">...</li>
    <li class="to-hide">...</li>
    <li class="to-hide">...</li>
    <li class="to-hide">...</li>
<ul>

2. How does it work?

We first obtain, from jQuery, an array containing the objects we want to-hide.

Then we create a named anonymous function that will be executed right after its definition -- it's the (function() { ... })(); pattern. Even if it is an anonymous function, we give it a name so that we are able to easily call it recursively.

Note that you can achieve the same thing without giving an anonymous function a name -- which may sound a little strange if you don't understand how JavaScript deals with scope -- with the more obscure version:

(function() {                            // Anonymous function without a name
    if (items.length == 0) {
        window.alert("The end.");
        return;
    }
    var toHide = jQuery(items[0]);
    items = items.slice(1);
    toHide.hide("100", arguments.callee); // Recursive call to anonymous function
})();

This time we used the fact that arguments.callee represents the function itself -- so no need to give an anonymous function a name.

The whole magic is inside this recursive anonymous function -- that is a closure.

The hideRec anonymous function captures the items array. After checking that there's still something inside, it will remove the first element and store it in the local toHide variable (properly wrapped with jQuery).

At the end, it uses jQuery to hide the element, and passes this anonymous function as the callback -- jQuery will call it again once it has finished the effect.

I hope this is clear enough.

Good luck!

like image 130
Bruno Reis Avatar answered Jun 13 '26 21:06

Bruno Reis



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!