Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
How to: code JavaScript using Twitter bootstrap best practices (theodo.fr)
45 points by baptou12 on May 5, 2014 | hide | past | favorite | 23 comments


A cleaner way to convert a function declaration into a function expression would be to use brackets

  (function() {
    //code here
  })();
This won't affect the return type of the statement; which in case of using ! will return boolean 'true' unless the function returns a truthy value. Plus using ! for this purpose, looks totally messy.


To extend upon this, you can also pass in references to decrease lookup time. That's why you see people doing:

   (function($,window) {
     //code here
   })(jQuery,window);


This reduces size after uglifying.

  (function(window, $, otherGlobal) {  
     $ = window.jQuery;
     otherGlobal = window.otherGlobal;

     //code here
  })(window);


This solves one of the problems that '!' does, but not the other. If this file is concatenated with one that looks like it would accept a function call, it will be an error, because javascript. e.g.

    (function(){/* stuff */}())
    (function(){/* other stuff */}())
Is interpreted as:

    (function(){/* stuff */)())(function(){/* other stuff */}())
To correct this, you also need a semicolon.

    ;(function() {
        //code here
    })();
Alternatively, if you can stomach it (I can't), you can use the !.


This is what I use- in fact, I've been confused by this thread because I've never seen the '!' hack before. Even though someone called in "javascript syntax 101." I must be using good sources to learn.


FYI, the blog post suggests that bootstrap is currently developped at twitter, which is not the case anymore @see http://getbootstrap.com/about/


You're right. This has been corrected.


"The ! converts the function declaration to a function expression" .... and i closed the tab


There's a good discussion over here: https://github.com/airbnb/javascript/issues/44


Oh god. Javascript's optional semicolon really has inflicted a lot of damage, hasn't it?


Horrible, isn't it? Baffling, quasi-random punctuation inserted to prevent random errors caused by poor design choices intended to make programmers' lives easier.


I remember when I used to rave on at my colleagues that it was amazing back in 2005.

How wrong I was.


You lose the return value over (function(){})(). That's an awful recommendation.


Yup! We only recommend !function(){}(); for a module where you just need your function to run. If you rely on the return value use (function(){})(); or (function(){}()); (more on this: https://github.com/airbnb/javascript/issues/21)


Second to this.


Why?


Well, when all is said in done, the statement the author makes is pretty much incorrect in every sense. `!function(){}()` is a type of immediately-invoked function expression. Even if the `!` weren't there, `function(){}` would still be a function expression (compare to `var fun = function(){};`, a function declaration).

Second, `!` in JavaScript does not convert a function declaration into a function expression; it invokes the NOT operation on whatever immediately follows it.

Examples:

   > !true;
   false

   > !false;
   true

   > !4;
   false

   > !undefined;
   true

   > !!undefined;
   false
So, basically what this code is doing is creating a function, calling it (with `()`), and then running a NOT operation on it.

I personally hate this kind of code because it's hacky and works by exploiting the interpreter. If you look at the examples of the `!` operator I gave, `!undefined` returns `true`, which is exactly what the author's code will return. Granted, the chances that you'll get bitten for using `!` over just a pair of parens is slim, you're still forcing the interpreter to waste [an incredibly small amount of] time performing useless operations just because the programmer was too lazy to type parentheses.

Much better, IMO, would be `(function() {})()` or, more safely and explicitly, `(function() {}).call(this)`, which sets the function expression's context to Window even in strict mode. `foo()` is syntactic sugar for `foo.call(undefined)` in strict mode and `foo.call(window)` in non-strict mode.


You mixed up your definitions of function declaration and function expression. In this case, if the '!' weren't there, it would indeed be a function declaration, but with improper syntax (removing the '!' would result in a syntax error).

What makes a function either an expression or declaration is simply whether the parser expects an expression or declaration in the given context. The grouping operator '()' and the NOT operator '!' both are parameterized by expressions, and so the Javascript parser treats functions passed to them as expressions. Unless located where an expression is expected, functions will default to declarations.


You're right, my mistake. Brain cramp :)


I liked one of the responses to the SO thread: http://stackoverflow.com/questions/3755606/what-does-the-exc...

    !function () {}()
This will also return the boolean opposite of the return value of the function, in this case true, because !undefined is true. If you want the actual return value to be the result of the call, then try doing it this way:

    (function () {})()
Why would you ever not want the actual return value of a function to be the result of calling that function?


Prepending a ! results in the parser picking up the line as a expression instead of a statement.

    function foo(){}; // statement
    var a = function() {}; // the right side of the = is a expression, a function keyword inside a expression does also not require a name
Also function statements are put into the scope before execution of the program begins, expressions on the other hand need to be evaluated.

So this will work:

    foo();
    function foo(){}
While this will throw the usual `Undefined is not a function` (it does not throw foo is not defined, because the var statement gets hoisted, meaning before the code is run the compiler will move all var statements to the top of the nearest scope (i.e. function)

    foo();
    var foo = function(){};


Now, as for why he closed the tab, first of all it is pretty clear that this is a very dumbed down explanation of the whole thing, and while there is a SO link it's not immediately clear that all operator tokens can trigger this behavior.


protip: you will have a better time if you read this as satire.


Oh my, this isn't satire.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: