Reputation: 916
I am following a tutorial for a basic parallax scrolling effect:
http://callmenick.com/2014/09/08/advanced-parallax-scrolling-effect/
It is a good tute and pretty easy to understand and implement but I came across some code I just can't quite get my head around.
(function(){
var parallax = document.querySelectorAll(".parallax"),
speed = 0.5;
window.onscroll = function(){
[].slice.call(parallax).forEach(function(el,i){
var windowYOffset = window.pageYOffset,
elBackgrounPos = "50% " + (windowYOffset * speed) + "px";
el.style.backgroundPosition = elBackgrounPos;
});
};
})();
I get that it loops through all elements with the class parallax, gets the Yoffset and sets the background position. But can anyone breakdown this line with an explanation?
[].slice.call(parallax).forEach(function(el,i)
UPDATE
Some great explanations below but is this a better solution than using jQuery like so:
$('.parallax').each(function(){
$this= $(this);
var window_y = (window.pageYOffset+1000);
var elBackgrounPos = "0 " + (window_y * speed) + "px";
$this.css('background-position', elBackgrounPos);
});
To me this is much more readable, but does the javascript version perform better or is more efficient in some ways?
Upvotes: 1
Views: 565
Reputation: 317
The parallax object is of the type NodeList, which doesn't have a forEach method.
However using JavaScript's call(), which exists on all objects, we can temporarily give it the ability to use forEach as if it were an array.
you could even shorten the code to be just [].forEach.call(parallax, function(el, i) {...})
call(), and apply() are methods you should definitely check out if you're not familiar with them
Upvotes: 1
Reputation: 2312
document.querySelectorAll
returns a NodeList, which is a special kind of DOM object. By using call()
, we can invoke the slice()
method of Javascript arrays to split the NodeList into something that allows us to then use the forEach
method, which is not available on NodeLists.
Try this out in the Javascript console of your browser:
var a = document.querySelectorAll('div')
a.forEach
b = [].slice.call(a)
b.forEach
You'll see that a.forEach will return undefined
and b.forEach will return
function forEach() { [native code] }
Basically it lets us manipulate the NodeList items in an easier way. You'll also see that the __proto__
property of b is []
while the __proto__
property of a is NodeList
. This is why b can call forEach
and a cannot.
Upvotes: 2