简体   繁体   中英

jQuery resize(), scroll(): good practice to use variables?

So my website is experiencing lag when scrolling. I just wanted to ask if it's a good practice to initialize the jQuery objects that you need in $(window).scroll(function () {} ?

For example:

$(window).scroll(function () {
  $thisContainer = $('.section #container');

  // 10 more initializations...
  $thisContainer.css(); // something like that...
}

I feel like it wouldn't be a good idea since this function gets called really often every time the user scrolls. And when it is called, those variables would be reinitialized. That as a result would waste a whole lot of memory and time.

Thanks!

In general you should avoid doing anything inside a callback that was fired by the scroll event because the callback will be executed for every pixel that the window is scrolled. However, depending on the application that you're building, some things simply cannot be avoided inside that callback.

Doing a lot of "expensive" manipulations or queries inside the scroll callback can totally freeze the browser and will make your application unusable, so you have to be very careful and performance cautious.

Here are some examples of good practices.

A general example:

Live example: http://jsfiddle.net/tfjyf0a3/

// Since we can get away with querying the elements outside of the callback 
// our application will be a lot snappier because we're doing less work for 
// every scrolled pixel. Always query DOM elements outside if possible.
var $output = $('#output');
var $window = $(window);

// This function is executed for every scrolled pixel, so we need to 
// avoid doing "expensive" queries or changing the DOM in here too.
function changeFontSize(scrollNumber) {
  // Setting the fontSize here is unavoidable because our application needs it. 
  $output.css('fontSize', scrollNumber <= 50 ? 18 : Math.floor(scrollNumber/10));
}

$window.on('scroll', function() {
  // Since `$(this)` here would be the window object, it's better to 
  // just use the previous reference named `$window`.
  // Querying the scrolled position here is unavoidable because our 
  // application needs it.
  var currentScroll = $window.scrollTop();

  // Saving a reference of the `scrollTop()` value is better when 
  // we need to re-use its value.
  $output.html(currentScroll + 'px');

  // We have to be cautious inside this function as well.
  changeFontSize(currentScroll);
});


// This is a good practice when you need to guarantee the execution of the function 
// when there isn't enough content in the body to cause a scrollbar in the Browser. 
// 
// The 'scroll' event will fire only when there is a scrollbar in the Browser.
$window.scroll();


Sometimes you will need to do "expensive" DOM manipulations, queries, or even Ajax requests inside the scroll's callback function. For example imagine building an application that implements a pattern known as infinite loading. In this application when the user has reached close to the bottom of the page by scrolling quickly or slowly, you will need to do the following:

  1. Check if the user has scrolled to the bottom.
  2. Check if there are more resources to load.
  3. Load the resources.
  4. Append the new resources to the DOM.

You definitely wouldn't want to execute all the steps above on every scrolled pixel. A very good practice for this situation is to delay the steps above. An example might look like this:

Delayed execution:

Live example: http://jsfiddle.net/35qb1b88/

var $output = $('#output');
var $window = $(window);
var timer;

function changeFontSize(scrollNumber) {
  $output.css('fontSize', scrollNumber <= 50 ? 18 : Math.floor(scrollNumber/10));

  // ...
  // load resources
  // append in DOM
  // ...etc
}

function scrollHandler() {
  var currentScroll = $window.scrollTop();

  $output.html(currentScroll + 'px');
  changeFontSize(currentScroll);
}

// This callback will be executed for every pixel but it will 
// do nothing if we're scrolling too fast because we're clearing
// the timeout. Only when scrolling has stopped and at least 100
// milliseconds have passed will the `scrollHandler` function run.
$window.on('scroll', function() {
  timer && window.clearTimeout(timer);
  timer = window.setTimeout(scrollHandler, 100);
});

$window.scroll();


The same principles would apply for the resize event too.

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