Belgian living here in Zürich
Weby stuff for 10 years
http://seld.be
OSS user & contributor
http://github.com/Seldaek
Recently co-founded Nelmio
We do Symfony2 & Frontend Performance consulting
http://nelm.io
There are things you may want and things that you may need. Wanting something is not a good reason to use it if it adds ambiguity or could potentially introduce bugs. (via @mikeal)
i++;
i += 1;
while (i < 50) {
doStuff(someStuff[i], i * 5, moreStuff[i]);
doMoreStuff(moreStuff[i++]);
}
while (i < 50) {
doStuff(someStuff[i], i * 5, moreStuff[i]);
doMoreStuff(moreStuff[i]);
i += 1;
}
i++;i++;
i += 2;
There are things you may want and things that you may need. Wanting something is not a good reason to use it if it adds ambiguity or could potentially introduce bugs. (via @mikeal)
alert(0 == false);
alert('' == false);
alert([] == false);
alert("frontendconf" == false);
alert("frontendconf" == true);
The above converts booleans to int first then "frontendconf" to int according to the ECMAScript coercion rules.
if ("frontendconf") {
alert("frontendconf" === "frontendconf");
}
Proper Consistent whitespace, enforce strict mode
No ++, no ==, no eval, force strict, etc.
*Interestingly dangerous
Max value of an array
var numbers = [3, 5, 10, 2, 3];
alert(Math.max.apply(null, numbers));
alert(Math.max(numbers[0], numbers[1], numbers[2], numbers[3], numbers[4]));
Concat arrays
var a = [1,2,3];
var b = ['a','b','c'];
Array.prototype.push.apply(a, b);
alert(a);
Array literals really are the way to go, yet..
alert(new Array(5+1).join('five '));
var factorial = function (n) {
if (!n || n == 1) {
return 1;
}
return n * factorial(n-1);
};
alert(factorial(3));
var factorial = function f(n) {
if (!n || n == 1) {
return 1;
}
return n * f(n-1);
};
alert(factorial(3));
alert(f);
var zomg = function n() {
alert(n);
};
zomg();
alert(n);
Self-referencing functions, without arguments.callee - which is deprecated
More than logical operators
Default values
var f = function (a) {
a = a || 2;
alert(a);
}
f(1);
f(false);
f();
alert('' && ('' || 'c'));
alert(null && (false || 'c'));
alert('a' && (false || 'c'));
alert('a' && ('' || 'c') && 'd' );
alert('a' && ('' || 'b') && false);
continue 2; in JS
var i, j;
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
continue;
alert('foo');
}
alert('bar');
}
alert('done');
var i, j;
main:for (i = 0; i < 3; i++) {
sub:for (j = 0; j < 3; j++) {
continue main;
alert('foo');
}
alert('bar');
}
alert('done');
Goto in JS
var something = true;
do {
alert('a');
if (something) {
break;
}
alert('b');
} while (false);
alert('c');
var something = true;
foo: {
alert('a');
if (something) {
break foo;
}
alert('b');
}
alert('c');
alert(Math.min() < Math.max());
alert(Math.min());
alert(Math.max());
var test = 'foo';
function foo() {
alert(test);
test = 'bar';
alert(test);
}
foo();
var test = 'foo';
function foo() {
alert(test);
var test = 'bar';
alert(test);
}
foo();
var test = 'foo';
function foo() {
alert(test);
var test = 'bar';
alert(test);
}
foo();
What JS sees:
var test = 'foo';
function foo() {
var test;
alert(test);
test = 'bar';
alert(test);
}
foo();
alert(~~27.5);
alert(Math.floor(~~27.5));
var month = 9, year = 2011;
var jdn = function(y, m, d) {
var tmp = (month <= 2 ? -1 : 0);
return ~~((1461 * (y + 4800 + tmp)) / 4) +
~~((367 * (m - 2 - 12 * tmp)) / 12) -
~~((3 * ((year + 4900 + tmp) / 100)) / 4) +
d - 2483620;
};
alert(jdn(2011, 12, 24));
alert(~~'FOO');
alert(Math.floor('FOO'));
alert(~~(-27.5));
alert(Math.floor(-27.5));
Keep types stable
function selectElements(selector) {
selector = document.querySelectorAll(selector);
return selector;
}
function selectElementsRealQuick(selector) {
var elems;
elems = document.querySelectorAll(selector);
return elems;
}
alert(selectElements('.slide'));
alert(selectElementsRealQuick('.slide'));
Keep types stable: Same object shapes
var f = function (obj) {
return obj.a;
}
f({a: 'b'});
f({a: 'c', foo: 'bar'});
Keep dense arrays
0..N (not N..0) or push
var arr = [], arr2 = [], i;
for (i = 0; i < 5; ++i) {
arr[i] = 'val';
}
arr2.push('val');
arr2.push('val');
arr2.push('val');
arr2.push('val');
arr2.push('val');
Avoid inline functions (many functions, all unique)
var asyncProgramming = function() {
doStuff(function() {
moar(function() {
yayNesting(function() {
areWeThereYet(function() {
alert(42);
});
});
});
});
};
End-tag open delimiter
<script>
document.write("<script src='lala'></script>");
</script>
<script>
<!--
document.write("<script src='lala'></script>");
-->
</script>
<script>
document.write("<scr"+"ipt src='lala'></sc"+"ript>");
</script>
<script>
document.write("<script src='lala'><\/script>");
</script>
"use strict";
var f = function () {
"use strict";
};
var sloppy = function () {
eval("var x = false;");
alert(x);
y = 'foo';
with (window) {
alert(y);
}
};
sloppy();
var strict = function () {
"use strict";
eval("var x = false;");
alert(x);
y = 'foo';
with (window) {
alert(y);
}
};
strict();
Other benefits
Security, debugging, performance, minimizability, showing off
Support: FF4+, Chrome13+, Safari5.1+, IE10+ (likely)
Upcoming version of the ES spec
for (var i = 0; i < 3; i++) {
setTimeout(function () {
alert(i);
}, 1);
}
alert(typeof i);
for (var i = 0; i < 3; i++) {
(function (i) {
setTimeout(function () {
alert(i);
}, 1);
})(i);
}
alert(typeof i);
for (let i = 0; i < 3; i++) {
let j = i;
setTimeout(function () {
alert(j);
}, 1);
}
alert(i);
Throwaway variables
Execute
let x = 1;
let y = 2;
let ( x = 5, y = 5 * y ) {
$.alert(x);
$.alert(y);
}
$.alert(x);
$.alert(y);
Non strict matching
var x, y;
[x, y] = ['a', 'b', 'c'];
alert(x);
alert(y);
Var swap
var a = 1,
b = 2;
alert(a + " / "+ b);
[a, b] = [b, a];
alert(a + " / "+ b);
Destructuring objects
var { a: x, b: y } = { a: 1, b: 2 };
alert(x + " / " + y);
Optional named arguments
var foo = function(opts) {
alert(opts.foo);
alert(opts.bar);
}
foo({ foo: 'FOO', bar: 'BAR' });
foo({ bar: 'BAR', foo:'FOO'});
var foo = function({ foo: name, bar: project}) {
alert(name);
alert(project);
}
foo({ foo: 'FOO', bar: 'BAR' });
foo({ bar: 'BAR', foo:'FOO'});
Shorthand notation
var {a, b, c} = {a: 10, b: 20, c: 30};
alert(a);
alert(b);
alert(c);
var f = function (a, b) {
var rest = [].slice.call(arguments, 2);
alert(rest);
}
f(1, 2, 3, 4);
var f = function (a, b, ...rest) {
alert(rest);
}
f(1, 2, 3, 4);
var f = function (a, b, c) {
alert(a + b + c);
}
var data = [1, 2, 3];
f.apply(null, data);
var f = function (a, b, c) {
alert(a + b + c);
}
var data = [1, 2, 3];
f(...data);
Modules
Generators
Proxies
Tons of syntax-sugar, maybe.
Try some of it with:
<script type="application/javascript;version=1.7">
// ...
</script>