views:

1835

answers:

26

Here are some gems:

Literals:

var obj = {}; // Object literal, equivalent to var obj = new Object();
var arr = []; // Array literal, equivalent to var arr = new Array();
var regex = /something/; // Regular expression literal, equivalent to var regex = new RegExp('something');

Defaults:

arg = arg || 'default'; // if arg evaluates to false, use 'default'

Of course we know anonymous functions, but being able to treat them as literals and execute them on the spot (as a closure) is great:

(function() { ... })(); // Creates an anonymous function and executes it

Question: What other great syntactic sugar is available in javascript?

+21  A: 

In Mozilla (and reportedly IE7) you can create an XML constant using:

var xml = <elem></elem>;

You can substitute variables as well:

var elem = "html";
var text = "Some text";
var xml = <{elem}>{text}</{elem}>;
Chris Noe
Really? Are there other engines which support that?
eyelidlessness
This is part of the E4X extension: http://en.wikipedia.org/wiki/E4X
Chris Noe
Just wondering: what can you do with that "xml" variable once you've created it? Just playing with it now in firebug, it looks as though it doesn't have any methods or properties and you can't add it to the DOM.
nickf
Helpful link: http://developer.mozilla.org/index.php?title=En/Core_JavaScript_1.5_Guide/Processing_XML_with_E4X
Chris Noe
You can do this in scala too!
Steve g
Rhino supports this as well (open source Javascript engine for Java): http://www.mozilla.org/rhino/
J c
@nickf: e4x is great!!! I've been using it for a while with JSDB to output HTML pages and do processing on XML.var x=<q><a>b</a></q>;x.a += <a c="1">cc</a>;x.a[0].@n = 3;for each (var c in x.children()) print("wow:"+c.toXMLString());(prints this:wow:<a n="3">b</a>wow:<a c="1">cc</a>)
Jason S
E4X literals are a security disaster due to cross-site-script-inclusion attacks, and really not noticeably better than just being able to say “var xml= new XML('<elem></elem>')” IMO.
bobince
@bobince If the attacker can inject Javascript, you're gone regardless of whether E4X is on or not
Charlie Somerville
@CharlieSomerville That's not the risk. E4X potentially turns ‘safe’ [X][HT]ML files into active JS. Please read http://code.google.com/p/doctype/wiki/ArticleE4XSecurity for background on this issue.
bobince
+16  A: 

Use === to compare value and type:

var i = 0;
var s = "0";

if (i == s)  // true

if (i === s) // false
Chris Noe
It's actually referred to as strict equal -- basically it avoids all the type conversions that otherwise have to happen when doing ==
olliej
other languages (PHP) also call it "identity" checking, ie: are these two values *identical*?
nickf
+3  A: 

This isn't a javascript exclusive, but saves like three lines of code:

check ? value1 : value2
levik
Is there an equivalent to this when not assigning a value (eg. fnName ? fnName : defaultFn;)?
eyelidlessness
No, the ternary operator is strictly for expressions; no statements
Josh Hinman
you can use it to evaluate anonymous functions, like this: "var myFunc = (browserIsIE ? function() { ... } : function() { ... })" . personally, I wouldn't recommend it since it's pretty confusing, but at least it's possible.
nickf
"evaluate" probably isn't the best word in that previous comment. Umm.. assign?
nickf
@eyelidlessness: Yes: fnName ? fnName() : defaultFn(); // on a line on its own, works
Ates Goral
Adding to my comment above, you could even do: (fnName ? fnName : defaultFn)();
Ates Goral
@Ates Goral: It "works" but throws a ReferenceError if fnName is undefined. That's hardly syntactic sugar.
eyelidlessness
Of course, you would only do this when you know the variables to be declared. You could even go: `(fnName || defaultFn)()`
Ates Goral
+3  A: 

A little bit more on levik's example:

var foo = (condition) ? value1 : value2;
VirtuosiMedia
You don't need the parenthesis. Ternary operators are also common to many other languages.
Ates Goral
The parentheses help when there is syntactical ambiguity in the conditional statement (eg determining which component of the conditional statement the ? applies to).
eyelidlessness
+14  A: 

Being able to extend native JavaScript types via prototypal inheritance.

String.prototype.isNullOrEmpty = function(input) {
    return input === null || input.length === 0;
}
steve_c
Just avoid doing this to Array: http://stackoverflow.com/questions/61088/hidden-features-of-javascript#118556
Chris Noe
This is true, but only if you use the for(a in b) loop. Typically I use frameworks, as I'm sure everyone else does. As a consequence I'm typically using .each()
steve_c
It's a potential problem if *any* code in your container uses for(a in b). And when that container is a browser, you could be breaking other code in your browser, (eg, that framework). I have been dinged by the one.
Chris Noe
Yep. Good points, Chris. I still count prototypal inheritance as one of the best features of JavaScript :)
steve_c
for(var i in obj) { if(!obj.hasOwnProperty(i)) { continue; } ... }
eyelidlessness
Yep, You should always use hasOwnProperty otherwise the loop will iterate over all properties up the prototype chain.
steve_c
+12  A: 

Multi-line strings:

var str = "This is \
all one \
string.";

Since you cannot indent the subsequent lines without also adding the whitespace into the string, people generally prefer to concatenate with the plus operator. But this does provide a nice here document capability.

Chris Noe
+18  A: 

Using anonymous functions and a closure to create a private variable (information hiding) and the associated get/set methods:

var getter, setter;

(function()
{
   var _privateVar=123;
   getter = function() { return _privateVar; };
   setter = function(v) { _privateVar = v; };
})()
Ash
took me a moment, but i got it. this IS neat.
matt lohkamp
I discovered a similar technique a while ago while looking through the swfobject source. Using closures to create private variables/methods is something I probably never would have thought of. It's kind of cool.
Herms
+21  A: 

Object membership test:

var props = { a: 1, b: 2 };

("a" in props) // true
("b" in props) // true
("c" in props) // false
Chris Noe
That is certainly more concise than props.a === undefinedThanks.
eyelidlessness
And it's true even if props = { a: undefined }.
ephemient
Oh right, that makes sense.
eyelidlessness
+1  A: 

I love being able to eval() a json string and get back a fully populated data structure. I Hate having to write everything at least twice (once for IE, again for Mozilla).

dicroce
I think this one deserves a code example.
Chris Noe
+7  A: 

Getters and setters:

function Foo(bar)
{
    this._bar = bar;
}

Foo.prototype =
{
    get bar()
    {
        return this._bar;
    },

    set bar(bar)
    {
        this._bar = bar.toUpperCase();
    }
};

Gives us:

>>> var myFoo = new Foo("bar");
>>> myFoo.bar
"BAR"
>>> myFoo.bar = "Baz";
>>> myFoo.bar
"BAZ"
insin
Can't wait til this is available universally.
eyelidlessness
Yes, it will be a bit nicer then the current approach I used.
Ash
@eyelidlessness it is in ECMAScript 5's Object.defineProperty which IE implements and other browsers can use __defineGetter__.
Eli Grey
IE8 only implements getters/setters for DOM objects, so it's useless when it comes to making your own object APIs neater :-/
insin
+2  A: 

The Array#forEach on Javascript 1.6

myArray.forEach(function(element) { alert(element); });
Pablo Cabrera
+1  A: 

I forgot:

(function() { ... }).someMethod(); // Functions as objects
eyelidlessness
+35  A: 

Getting the current datetime as milliseconds:

+new Date()

The unary + coerces the Date value to Number. The result is the same as either of these expressions:

Number(new Date())
new Date().getTime()

For example, to time the execution of a section of code:

var start = +new Date();
// some code
alert((+new Date() - start) + " ms elapsed");
Chris Noe
This is, in fact, the best javascript syntactic sugar. A winnar si yuo.
eyelidlessness
You don't need the +, it works just fine without it.
RedFilter
OrbMan, that probably depends on the context; if passing it as an argument, it may be coerced to an Object rather than to a Number or a String, in which case the + would have already coerced it to a Number. In fact, + appears to function as a shorthand for parseInt(value, 10).
eyelidlessness
Correction: it does have some difference from parseInt(value, 10). For instance, +[3] and parseInt([3], 10) are both equal to the number 3, but +[3, 4] == NaN and parseInt([3, 4], 10) == 3.
eyelidlessness
Er... all of those instances of parseInt(value, 10) ought to be parseFloat(value). And Chris Noe, sorry for the comment spam ;)
eyelidlessness
You don't need the `()` :)
Paul Irish
A: 

As an aside note (with the added benefit of potentially inciting a religious war):

Funny, but all the things mentioned here were already in LISP 30 years ago.

Which browsers can you script with it?
Chris Noe
How is browser scripting related to syntactic sugar?
Jonathan Arkell
How many browser do you know that will run my LISP scripts?
Pim Jager
Jonathan Arkell, the topic discusses syntactic sugar *in Javascript*, which is both primarily used as a browser scripting language and the most widely used browser scripting language.
eyelidlessness
+9  A: 

Repeating a string such as "-" a specific number of times by leveraging the join method on an empty array:

var s = new Array(iRepeat+1).join("-");

Results in "---" when iRepeat == 3.

J c
+8  A: 
var tags = {
    name: "Jack",
    location: "USA"
};

"Name: {name}<br>From {location}".replace(/\{(.*?)\}/gim, function(all, match){
    return tags[match];
});

callback for string replace is just useful.

Serkan Yersen
A: 

int to string cast

var i = 12;
var s = i+"";
Martijn Laarman
This doesn't look more "sugary" to me than doing a straight i.toString() or String(i). Short != Sugar.
Ates Goral
+3  A: 

Following obj || {default:true} syntax :

calling your function with this : hello(neededOne && neededTwo && needThree) if one parameter is undefined or false then it will call hello(false), sometimes usefull

vvo
A: 

Assigining the frequently used keywords (or any methods) to the simple variables like ths

  var $$ = document.getElementById;

  $$('samText');
Ramesh Vel
+7  A: 

Resize the Length of an Array

length property is a not read only. You can use it to increase or decrease the size of an array.

var myArray = [1,2,3];
myArray.length // 3 elements.
myArray.length = 2; //Deletes the last element.
myArray.length = 20 // Adds 18 elements to the array; the elements have the undefined value. A sparse array.
pramodc84
A: 
element.innerHTML = "";  // Replaces body of HTML element with an empty string.

A shortcut to delete all child nodes of element.

pramodc84
That's not really Javascript, it's DOM, and it's currently non-standard at that.
eyelidlessness
and leaks memory...
galambalazs
A: 

JavaScript's Date class providing a semi-"Fluent Interface". This makes up for not being able to extract the date portion from a Date class directly:

var today = new Date((new Date()).setHours(0, 0, 0, 0));

It's not a fully Fluent Interface because the following will only give us a numerical value which is not actually a Date object:

var today = new Date().setHours(0, 0, 0, 0);
palswim
A: 

Default fallback:

var foo = {}; // empty object literal

alert(foo.bar) // will alert "undefined"

alert(foo.bar || "bar"); // will alert the fallback ("bar")

A practical example:

// will result in a type error
if (foo.bar.length === 0)

// with a default fallback you are always sure that the length
// property will be available.
if ((foo.bar || "").length === 0) 
roosteronacid
+3  A: 

Like the default operator, || is the guard operator, &&.

answer = obj && obj.property

as opposed to

if obj {
    answer = obj.property;
}
else {
    answer = null;
}
Skilldrick
A: 

Create an anonymous object literal with simply: ({})

Example: need to know if objects have the valueOf method:

var hasValueOf = !!({}).valueOf

Bonus syntactic sugar: the double-not '!!' for converting pretty much anything into a Boolean very succinctly.

mkoistinen
+1  A: 

In parsing situations with a fixed set of component parts:

var str = "John Doe";

You can assign the results directly into variables, using the "destructuring assignment" synatx:

var [fname, lname] = str.split(" ");
alert(lname + ", " + fname);

Which is a bit more readable than:

var a = str.split(" ");
alert(a[1] + ", " + a[0]);

Alternately:

var [str, fname, lname] = str.match(/(.*) (.*)/);

Note that this is a Javascript 1.7 feature. So that's Mozilla 2.0+ and Chrome 6+ browsers, at this time.

Chris Noe
I tried this in the Safari Javascript console and it results in a parse error.
eyelidlessness
Snap, I guess I've only used this in Firefox. I have add a browser compatibility note.
Chris Noe
It doesn't work on Chrome 6. It gives `SyntaxError: Unexpected token [`.
RaYell
A little research starts to reveal that chrome's 1.7 is not entirely standard. There is reportedly a problem with let as well: http://stackoverflow.com/questions/300185/google-chrome-javascript-version#1125353
Chris Noe