2. Agenda
Cover proven practices about how to write better
JavaScript
Lots of slides (50+) but a lot are code we will talk about
and see what is right & what is wrong
Assumption: You can read JavaScript (or fake it)
3. JavaScript is a sloppy
language, but inside it
there is an elegant,
better language.
Douglas Crockford -
4. Situation 1
code
1. var i=0;
2. function demo(){
3. for (i=0; i<10; i++){
4. // do stuff
5. }
6. }
7. demo();
8. // what is i?
output
10
5. Situation 1 cont.
code
1. function demo(){
2. i = 50;
3. }
4. demo();
5. // what is i?
output
50
7. Always use var - fixes
1. var i=0;
2. function demo(){
3. var i = 0;
4. for (i=0; i<10; i++){
5. print("demo");
6. }
7. }
8. demo();
9. // what is i?
8. Always use var - fixes
1. var i =0;
2. function demo(){
3. for (var i=0; i<10; i++){
4. print("demo");
5. }
6. }
7. demo();
8. // what is i?
9. Situation 2
code
1. function setspan(num, text)
2. {
3. eval("myspan" + num + ".innerText = '" + text + "'");
4. }
data
1. myspan1.innerText = 'it ain't what you do, it's the way thacha do it';
output
//syntax error
11. Avoid eval
eval is hard to get right and there are many many
situations out of your control you need solve
eval runs code – so you are saying you trust the user
to write code
Modern browsers pre-compile JavaScript, eval doesn’t
benefit from this!
12. Situation 3
code
1. function doSomething(someValue){
2. //...
3. }
4.
5. setTimeout("doSomething('3 seconds elapsed. Time is up.');", 3000);
code
1. var sum = new Function('op1', 'op2', 'return op1 + op2;');
2. var result = sum(10, 20); // ==> 30
13. Avoid eval part 2
eval can appear in sneaky locations in JavaScript
Timers – SetTimeout & SetInterval
Function contstructors
14. Avoid Eval Part 2 Fixed
1. setTimeout(function(){
2. doSomething('3 seconds elapsed. Time is up.');
3. }, 3000);
1. function sum(op1, op2){
2. return op1 + op2;
3. }
15. Situation 4
code
1. var total = variable1 + variable2;
2. print(total);
data
1. var variable1 = "1";
2. var variable2 = "2";
output
1. 12
I’d never be so stupid to add strings?
1. var variable1 = document.elements["inputA"].value;
16. Situation 4
code
1. var total = parseInt(variable1) + parseInt(variable2);
2. print(total);
data
1. var variable1 = "1";
2. var variable2 = "2";
output
3
data
1. var variable1 = "064"; 64 base 8 = 52 base 10
2. var variable2 = "032"; 32 base 8 = 26 base 10
output 52 + 26 = 78
78
17. Unary Operator
JavaScript has one type for numbers
Other primitives: Object, string & boolean, RegExp,
Math, Array, Date, Error, NativeError (mostly)
parseInt & parseFloat require you to set the numeric
base the number is in – else it will try and guess
18. Unary Operator
(+<variable>) is the right way to get an number
Even though braces are optional - you should always
have them, else it is hard to work out what is addition
and what is unary
19. Unary Operator Fixed
code
1. var total = (+variable1) + (+variable2);
2. print(total);
data
1. var variable1 = "1";
2. var variable2 = "2";
output
3
data
1. var variable1 = "064";
2. var variable2 = "032";
output
96
20. Unary Operator vs. parseInt
code
1. parseInt("567Gb");
output
567
code
1. +"567Gb";
output
NaN
21. Situation 5
1. function validate (idNumber) {
2. var year = getYear(idNumber);
3. // omitted
4. }
5.
6. function getYear(idNumber) {
7. // omitted
8. }
22. Namespaces
Group things into namespaces, so that they are
properly scoped.
Expose only what you need to expose.
There are at least 5 different ways to do namespaces –
pick one as a team. I’m going to show you my favourite
next – the Self-Executing Anonymous Function Public
& Private.
26. Separation of concerns
Taking namespaces further – practise separation of
concerns
Put JavaScript into separate files – do not inline in the HTML file.
Build as much of your JavaScript do it is not tied to HTML or CSS
Let HTML do what it is good at (organisation of content), CSS do what it
is good at (presentation style) & JavaScript do what it is good at
bad
1. itemX.color = "#fff";
2. itemX.font-family = "Consolas";
good
1. itemX.style = "codeBlock";
31. Avoid with - Fixed
1. var o = document.forms["mainForm"].elements;
2. o.input1.value = "junk";
3. o.input2.value = "junk";
32. Situation 7
code
1. var o = new Object();
2. o.name = 'Jeffrey';
3. o.lastName = 'Way';
4. o.someFunction = function() {
5. console.log(this.name);
6. }
33. Prefer object literals
PREFER
Allows for more flexibility, cleaner code (no
constructors) & you don’t need to worry about
constructor parameter ordering.
34. Prefer object literals - fixed
1. var o = {
2. name : 'Jeffrey',
3. lastName : 'Way',
4. someFunction : function() {
5. console.log(this.name);
6. }
7. };
1. var o = {};
35. Situation 8
code
1. var a = new Array();
2. a[0] = "Robert";
3. a[1] = "MacLean";
37. Prefer object literals - fixed
1. var o = ["Robert", "MacLean"];
A common error in JavaScript programs is to use an
object when an array is required or an array when an
object is required. The rule is simple: when the property
names are small sequential integers, you should use an
array. Otherwise, use an object.
Douglas Crockford
38. Situation 9
code
1. var x = "123";
2. var y = 123;
3. x == y;
output
1. true
40. Use === rather than ==
== is equality
=== is identity
Equality checks type, if type differs will convert and
then check values
Identity checks type, if type differs will return false
43. ALWAYS end with semicolon
Semicolon is a statement separator in JavaScript
Putting semicolon’s in is optional – but then JavaScript
will guess where the statements will be separated
Be consistent
44. ALWAYS end with semicolon - fixed
code
1. function x(){
2. return 6;
3. }
4. x();
output
6
45. Situation 11
code
1. var a = 1,2;
2. var b = 1,2,3;
3. var c = 99+1,99
output
2
3
99
46. Avoid the comma operator
Comma operator – not the comma separator in arrays
– can lead to very tricky to understand code.
Unless you are 100% sure about it – don’t use it
Even when you are 100% sure – add comments for the
rest of us
47. Comma Operator - Fixed
1. var r = [], n = 0, a = 0, b = 1, next ;
2. function nextFibonacci() {
3. next = a + b;
4. return b = (a = b, next);
5. }
6. while(n++ < 10) {
7. r.push(nextFibonacci());
8. }
9. r; //[1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
48. Situation 12
1. foo = "awesome";
1. var foo = "awesome";
2. delete foo;
1. var o = { foo: 123, foo: 456 };
1. function eval() { }
1. eval("var a = false;");
2. print(a);
1. with
49. Turn Strict mode ON
All code runs in the strict context which makes your
code more stable, finds more coding problems and
raises more exceptions.
Can define strict in a function
50. Turn Strict mode ON
What does it do?
ECMAScript 3 deprecated methods raise exceptions
Unassigned variables throw exceptions
Delete throws exceptions
Duplicate properties throw exceptions
Hijacking eval throws exceptions
Eval code is sandboxed
With is gone
MORE!!!
Full info: http://dmitrysoshnikov.com/ecmascript/es5-
chapter-2-strict-mode/
51. Turn Strict mode ON
For this talk it helps with:
Situation 1 – always use var. Undeclared variables will syntax error
Situation 4 – parseInt defaults to decimal in strict mode
Your mileage may vary here: Chrome 19 does it wrong IE 10 does
it right
Situation 6 – with. Always gives syntax error
52. Turn Strict mode ON - Fixed
1. "use strict";
1. function demo(){
2. "use strict";
3. // more
4. }
1. foo = "awesome"; // exception
2. var bar = "awesome";
3. delete bar; // exception
4. var o = { foo: 123, foo: 456 }; // exception
5. function eval() { } // exception
6. eval("var a = false;");
7. print(a); // undefined
8. with //syntax error
What happens if someone else writes a method with the same name in the global scope?Does the person using my code need to see all that?Stolen “keywords”