jquery slide show - why does this code work?

2019-07-16 12:04发布

问题:

I was in the middle of coding a slideshow in javascript using jquery, when I ran into something that was doing what my several lines of code was doing in a couple lines.

Problem is, I don't comprehend how it works so I can modify it.

var imgs = [
        'image1.jpg',
        'image2.jpg',
        'image3.jpg'];
        var cnt = imgs.length;

    $(function() {
        setInterval(Slider, 4000);
    });

    function Slider() {
    $('#imageSlide').fadeOut("slow", function() {
       $(this).attr('src', imgs[(imgs.length++) % cnt]).fadeIn("slow");
    });
    }

This is the line that gets me:

[(imgs.length++) % cnt]

I'm reading that as

3+1 % 3 = 1

Now every time it executes, none of that code appears to be modifying any of the variables. cnt will always equal imgs.length (3), imgs.length++ doesn't actually modify it, it just adds one for that single execution, correct?

So matter how many times it executes, it will always be imgs[1] yet when I execute the code, it runs properly through all the array objects.

EDIT:

I simply added alert(imgs.length); and confirmed that ++ does actually change the variable, but it still doesn't make sense to me.

The first run, imgs.length = 4 after ++. 4 % 3 = 1 so it should run array object [1] not [0]?

Second run, 5 % 3 = 2

Third run, 6 % 3 = 0

etc etc.. but it shouldn't ever reset. However, if I put a alert(imgs.length % cnt); it only returns 0, 1, 2 than it resets.

Why?

回答1:

the return value of imgs.length++ is 3 therefore 3 % 3 = 0 but imgs.length will be 4 and the imgs array will contain 4 items.

try it in console:

var x = [ 1, 2, 3 ]
x.length++
=> 3
x.length++
=> 4
x.length++
=> 5
x
[1, 2, 3, undefined, undefined, undefined]

so every time imgs.length++ is called itt will append one item to the array. so not a nice code but short :)

EDIT: the why is easy to answer, in the start it contains cnt number of elements, so the code will step on every image and the starts from the beginning of it. so if the imgs array contains 5 items it will step through the 5 items and starts from the beginning.

the only problem with this code, that the array will be increased every time and the memory will be eaten by the browser.



回答2:

I'm sure you're aware that imgs.length++, if it were applied to any other variable, would be adding one to it, modifying the original variable.

var x = 1;
alert(x++); // alerts 1
alert(x); // alerts 2

Sure enough, that's what's going on.

The script increments the length of the imgs array on every run, so it moves from 3 to 4 to 5 to 6, etc. I'm not an expert on Javascript internals, so I'm not sure if that has any effect on performance, but if you understand that length is, in fact, a writable property, it all makes sense.



回答3:

(imgs.length++) % cnt

will cause the images to loop through every image, over and over.

the percentage sign (%) in JavaScript means it uses Modulus (division remainder) operator.

Examples:

  • 0 % 3 = 0
  • 1 % 3 = 1
  • 2 % 3 = 2
  • 3 % 3 = 0
  • 4 % 3 = 1
  • 5 % 3 = 2 etc...


回答4:

Well, every 4:th second that the function Slider runs it expands the array, so you get:

3+1 % 3 = 1
4+1 % 3 = 2
5+1 % 3 = 0

and so on :)



回答5:

I'm not 100% sure in javascript but every other language I know imgs.length++ is the same as saying imgs.length = imgs.length + 1 so that should be getting modified.

I'd consider it a "clever trick" that should be documented if used at all. It kinda breaks the semantics of what length means, so while logically correct to a computer it doesn't quite make sense in relation to the property name

So I guess it actually does change the length, but I still wouldn't recommend using it without documenting it. A more clear method would be to declare a new var i = 0 and replace imgs.length++ with i++, because although it doesn't probably matter in this case, if you're doing anything else with the array, the length is now probably not what you expect it to be.

Regarding the edit:
6 % 3 is 0 not 3.
Modulo (in programming, slightly different in purely math term) means divide and take the remainder.
6 / 3 = 2 with a remainder of 0.
7 / 3 = 2 with a remainder of 1.
8 / 3 = 2 with a remainder of 2.
9 / 3 = 3 with a remainder of 0,



回答6:

If you want your code to be more readable in the future, I would personally suggest you change your code to something like this:

var imgs = [
    'image1.jpg',
    'image2.jpg',
    'image3.jpg'];
var i = 0;

$(function() { // This is a shortcut for $(document).ready();
    setInterval(Slider, 4000);
});

function Slider() {
   $('#imageSlide').fadeOut("slow", function() {
      i = (i+1) % imgs.length;
      $(this).attr('src', imgs[i]).fadeIn("slow");
   });
}