简体   繁体   中英

How to use variables in imagesLoaded callback function?

I'm trying to do something very simple, but I'm obviously doing something wrong. Here is the code:

var targets = Array(
    $('.someDiv'),
    $('.myDiv')
    );
// This "for" loop check if the Class exists and if so it runs a code
for (var i = targets.length - 1; i >= 0; i--) {
    // make the target a jQuery object
    var $target = targets[i];
    // if the target exists
    if ( $target.length > 0 ) 
    {
        console.log($target);
        // run some code after every image is loaded
        $target.imagesLoaded( function()
        {
            console.log($target);
            $target.addClass('blue');
        });
    }
}

which somehow doesn't work. The JsFiddle example is here

Is it just impossible to pass a variable without hacking imagesLoaded plugin? Or am I missing something?

Good news: Your code works!

var myVar;
$('.myDiv').imagesLoaded( function() {
    console.log(myVar);
});

myVar is undefined as you did not define it.

... try var myVar = "Hello World";

If you want the variable to retain the value it had when calling imagesLoaded() , you can use an IIFE:

var myVar = 'someContent';

(function(myVar) {
    $('.myDiv').imagesLoaded( function() {
        console.log(myVar);
    });
})(myVar);

Take this example:

var myVar = 'some content';

(function(myVar) {
    setTimeout(function() {
        console.log(myVar);
    }, 1000);
})(myVar);

myVar = 'some other content';
console.log(myVar);

It will log some other content and then, a bit later some content , as was the initial value.

The problem is that the imagesLoaded callback is fired after you have already iterated over the elements. Which means that by the time the first callback is fired, $target is a reference to the last element in the array.

Fortunately, since you are just trying to get a reference to the element that imagesLoaded was called on, you can get a reference to it with this .

Updated Example

var targets = [$('.someDiv'), $('.myDiv')];

for (var i = 0; i < targets.length; i++) {
    var $target = targets[i];

    if ($target.length) {        
        $target.imagesLoaded(function () {
            $(this).addClass('blue');
        });
    }
}

Alternatively, you could also use the $.each() function in order to store the context on each iteration:

Updated Example

var targets = [$('.someDiv'), $('.myDiv')];

$.each(targets, function (i) {
    var $target = targets[i];

    if ($target.length > 0) {
        $target.imagesLoaded(function () {
            $target.addClass('blue');
        });
    }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM