6

Would somebody mind to explain me what is the difference between these scripts below? The first one found here on Stack Overflow, the second one is my own version that I better understand but is not working. Why doesn't it work by the way?

1.

(function blink() { 
  $('.blinkMe').fadeOut(500).fadeIn(500, blink); 
})();

2.

function blink() { 
  $('.blinkMe').fadeOut(500).fadeIn(500, blink); 
  blink();
}
blink();
1
  • The second one throws a stackoverflow exception. It should not call itself. Commented May 14, 2016 at 11:52

6 Answers 6

11

The first example is an Immediately-Invoked Function Expression (IIFE). It is a function which immediately executes itself after creation. IIFE is a common JavaScript design pattern used by most popular libraries (jQuery, Backbone.js, Modernizr, etc) to place all library code inside of a local scope.

In ES6 this can be rewritten using the Arrow function if you want the .blinkMe to blink just once:

(() => $('.blinkMe').fadeOut(500).fadeIn(500))();

You can chain as many fadeIn and fadeOut functions as you want of course. If you want it to loop infinitely I'd suggest the IIFE way.

More info about IIFE here.


About your second example. You're calling the function inside your own function (also known as recursive loop). In your case this creates an infinite loop, that's why it doesn't work. Remove the blink(); inside the function and it will work:

function blink() { 
    $('.blinkMe').fadeOut(500).fadeIn(500, blink); 
}
blink();

Besides with javascript you can also solve this issue with CCS3 animations. CSS3 animations run in a separate thread. This is a solution without jQuery:

(function blink() {
  document.getElementsByClassName('blinkMe')[0].className += ' blinkActive';
})();

// Arrow function:
//(() => document.getElementsByClassName('blinkMe')[0].className += ' blinkActive')();
.blinkMe {
  width: 80px;
  height: 80px;
  background: deepskyblue;
}
.blinkActive {
  -webkit-animation: blink 1s infinite;
  animation: blink 1s infinite;
}
@-webkit-keyframes blink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0; }
}
@keyframes blink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0; }
}
<div class="blinkMe"></div>

I don't know how many elements you want to blink on your page, if it's just one element you can use ids instead of classes. Keep in mind that the @keyframes rule is not supported in IE9 or earlier versions and Opera Mini: Link.

Sign up to request clarification or add additional context in comments.

7 Comments

improve...I think imporant is this sentense "the code here is executed once in its own scope" and therefore this pattern is common used by jQuery plugins.
@daremachine I've updated my answer with additional info.
"In your case this creates an infinite loop, that's why it doesn't work" about the infinite loop isn't true. The correct versions are infinite loops (otherwise it would stop blinking). The incorrect version is an exponential loop, that is why it crashed.
Your first code snippet doesn't work -- blink is undefined.
@MasterDJon no, the callback is never called because the JS thread is in an infinite loop that never yields.
|
7

The first is a IIFE . That is, the function is immediately invoked (executed) after it is declared. It is not attached to the global window object and so does not pollute it.

The second function is exponentially recursive. Every time it is run, it calls itself twice more, once as a callback to the fadeIn jquery method, and once more in the function body.

Comments

6

In this snippet, a named function is created, then immediately executed once in an Immediately-Invoked Function Expression. The function name is only available to itself, so it can again be called within the closure of the function body, in this case as a callback to the fadeIn function.

(function blink() { 
  $('.blinkMe').fadeOut(500).fadeIn(500, blink); 
})();


In this snippet, a named function is created, and called. Additionally, the function again calls itself, which will create an infinite recursion, which is why it fails. Unlike the last snippet, blink will also be available outside the function closure itself.

function blink() { 
  $('.blinkMe').fadeOut(500).fadeIn(500, blink); 
  blink();
}
blink();

Removing the blink() call inside the function itself as follows will make it function nearly identical, except for the different in blink scope.

function blink() { 
  $('.blinkMe').fadeOut(500).fadeIn(500, blink); 
}
blink();

Comments

6

The line $('.blinkMe').fadeOut(500).fadeIn(500, blink); already calls the blink when ending. So calling back blink() is like having twice the function called (and even more on each call). So this call was the problem.

EDIT : But as I just learned today, the timers aren't executed on a different thread in JavaScript. So, the blink() within the blink function takes all the executions frames and the blink callback is never called, but it is still registered to be called. As, I tested by adding a maximum number of iteration that the within blink() could be called.

function blink() { 
  $('.blinkMe').fadeOut(500).fadeIn(500, blink); 
  //blink();
}
blink();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<span class="blinkMe">Blinking</span>

Comments

2

This is a recursive function (animation).

According to the jQuery docs, fadeIn() takes two arguments: duration (in ms) and complete. The second argument is a function that is called once the animation is complete. It can be itself, or another function.

In the second function you are calling blink() again and again... but the second and the third never comming. Best way is the first.

Comments

2

Your function works, but the Navigator blocks it because of too much recursion. because you are callling blink() just after you fadeIn just try,

function blink() { 
  $('.blinkMe').fadeOut(500).fadeIn(500, blink); 
  //remove this call which causes too many recursions 
  //blink();
 }
//then call the method
 blink();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.