4

Possible Duplicate:
What does the exclamation mark do before the function?

I'm maintaining an existing site with a "tweet" button, which appears to come from this page

A colleague here brought up a great question: Why does this script tag reverse the (undefined via no return statement) value of this self-calling function? (pretty-fied for ease of reading, original is at link)

<script>
  !function(d,s,id) {
//^--- that
    var js,fjs=d.getElementsByTagName(s)[0];
    if(!d.getElementById(id)) {
      js=d.createElement(s);
      js.id=id;
      js.src="https://platform.twitter.com/widgets.js";
      fjs.parentNode.insertBefore(js,fjs);
    }
  }(document,"script","twitter-wjs");
</script>

To my non-JS-pro eyes, that appears to be flipping the boolean value of undefined, thereby allowing the entire <script> tag to evaluate to true. For what it's worth, that is a totally foreign idea to me (that <script> tag has an expression value).

My expectation is that there is some specific browser out there for which a <script> tag's boolean value (yes, I feel crazy even typing that) matters.

So the basic question is this: Does a <script> have a meaningful "expression" value to any browsers you know of? and What is the implicit meaning of a true vs. false in this case?

Community
  • 1
  • 1
Chris Trahey
  • 18,202
  • 1
  • 42
  • 55
  • @Quentin, Could you post a quick answer pointing to the other question? I don't think this is quite an exact duplicate: I was under the impression that the value of the guts of a ` – Chris Trahey Oct 24 '12 at 17:15

2 Answers2

4

An explanation of what is going on and why...

In Javascript, you have function statements and function expressions. The two of them are similar, but not exact.

Function statement

function myTest() {return true;}

Function Expressions

var f = function() {return true;}
alert(f()); //

alert(function() { return true}); // Return value is used

// and even

(function(x, y) {
  var z, x; // private variables, hidden from the outside scope
  var r = x  + y;
  // Return value is ignored.
}(1, 2));

// The ! can be used to start a function expression too.
// This is totally legal Javascript, but it isn't in the normal
// "vernacular" of the langage
!function(x, y) {
  var z, z1; // Private vars
  // Do something with side effects
  // Return value is ignored.
}(x, y);

Updated due to comments

//The following code works identical:
var v1 = (function(a, b) {return a+b}(1,2));
var v2 = (function(a, b) {return a+b})(1,2);
var v3 = function(a, b) {return a+b}(1,2)

I prefer the first form because it lets me use the block matching tools on my editor, and the f1 form is preferred by the sometimes useful programs JSLint and JSHint.

All create a function expression and then invoke it immediately. In this case, the parens are not needed by the Javascript compiler, but they serve as a very useful hint to the reader that this is not a normal assignment.

On the other hand, you must have something to tell the JS engine that you have a function expression instead of a function statement. The = sign above works, but when there is no assignment, you need to start off with some kind of operator, be it (+!

!function(x, y) {alert(x, y)}(1, 2);

The leading operator makes it an expression. The () in the above examples force it to an expression as well.

Jeremy J Starcher
  • 23,369
  • 6
  • 54
  • 74
0

This code creates a new script tag and adds it before the first element of type script if there's no script element with id twitter-wjs.

Since ! is the NOT operator in Javascript, it evaluates to true when its operand can be converted to false (in this case, when no element with id twitter-wjs exists, document.getElementById("twitter-wjs") returns undefined, and this in Javascript is a falsey value so the result in conjunction with ! operator will be true and the block of code inside the if gets executed. Any object in Javascript will be true when checking for its boolean value (try doing !![Object] and you will prove it), so the if block won't be executed when any element is returned by document.getElementById().

UPDATE:
Regarding to your comments, I see @JeremyJStarcher answer is ok, but I am adding something:
In your code you have a function expression. for function expressions an identifier is not needed. But when executing, the Javascript interpreter may confuse and think of it as a function declaration. In function declarations, the identifier is not optional, and so the interpreter will throw a Syntax Error. For avoiding this, ! operator is being used here so it will be treated as a function expression.

Pablo
  • 360
  • 3
  • 13
  • Sorry for the confusion, I think you've answered as though I was curious about the second `!`. Note that I am asking about flipping the return "of this self-calling function", and the question in general is scoped around truthyness of an entire ` – Chris Trahey Oct 24 '12 at 17:10
  • I have edited the question to make that more clear. – Chris Trahey Oct 24 '12 at 17:13