可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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");
});
}