When not specified, much of this knowledge comes from Java Script Patterns by Stoyan Stefanov, and the JavaScript Pocket Reference (3rd Edition) by David Flanagan. I personally found the JavaScript Pocket Reference to be the most valuable of the two.
This is by no means a comprehensive java script language overview, but it does provide a good bit of technical information for a beginner in the language. It mostly just covers some key concepts that can help improve code quality, and some gotchas of the language. It is recommended you have used Javascript a little bit prior to reading this.
I may update this from time to time.
Code Quality
Maintaining code quality is one of the most important aspects of creating sustainable software. In this section, we’ll outline a few aspects of JavaScript, which can create gotchas, or can save you from them.
Use Strict
At the beginning of any function, or script, you can put a static string “use strict”. In the case of older versions of JavaScript, it’s just interpreted as an unassigned string literal. In the case of newer versions, it’s intended to force the use of good practises. Some of the things that are considered bad practise, and will result in an error if “use strict” is in use, are…
- use of a variable not declared with the *var* keyword (e.g. var myVariable;), will result in an error. Since all variables created without a “var” declaration are instantly turned into globals, causing potentially undesired side affects, this is a good thing. If not using strict mode, declaration of variables without the “var” keyword is not recommended.
- attempting to write to non-writable properties, a getter only property, a non-existent property, a non-existent object, or a non-existent variable, will throw an error (1)
- duplicating parameter names in a function (1)
- use of variable names that are common language keywords are not allowed. Examples are “arguments”, “eval”, etc (1)
- The “this” keyword is no longer available to global functions; i.e. those functions that are not members of an object. (1)
Patterns
Array Length Caching
// Caching array length is between 2 and 190 times faster, depending on the browser var myArray = [0,2,4,6,8]; for (var i = 0, max = myArray.length; i < max; i++) { } // ref: (3) p.g. 16 |
Configuration Objects
It’s a good practise to use configuration objects for passing parameters. Some of the reasons to use them are…
- They prevent changing of the API, when you add or remove parameters, there by making API modifications easier.
- The order of parameters no longer matter.
- You can skip optional parameters without worrying about putting those at the end of the parameter list.
function doSomething(options) { console.log(options) }; doSomething({ name: 'Trent', gender: 'male', occupation: 'full time nerd'}); |
Furthermore, jQuery has functionality to allow merging of what is passed into a function with default values. The default values are overwritten if present in the parameter object, and a new object is returned.
Functions
Lexical Scope
JavaScript functions use lexical scoping (known as closures). This means that variables in the immediate parent code are available to the code within the closure, and in fact are the variable that is used regardless of the scope of the call.
var myGlobal = "global"; function myFunction() { var myVariable = "local"; function f() { return myVariable;} } myFunction() // returns "local". |
Objects
Functions themselves are objects. This functionality allows for turning a function into a constructor, which sets up an object instance. It also allows for requesting the function’s name via it’s toString() method.
They also have their own *this* keyword, which refers to the object they are contained within, or the global object if they are not a member of another object. With ECMAScript 5, and the strict mode enabled, the *this* keyword is undefined when the function is not part of an object.
Language Quirks
Javascript can be quite quirky at times. And if you’re not aware of some of the issues, it’s rather annoying to figure out what’s happening.
Expressions
Some interesting expressions that are fairly important to know.
var myArray = myArray || []; // checks for undefined, then assigns an empty array var myVar = 2; var myVar2 = "2"; myVar == myVar2; // true myVar === myVar2; // false - operator strictly checks for equality without type conversions. false == 0; // true - use === instead "" == 0; // true - use === instead [0,1,2] == "0,1,2"; // true - use === instead |
Hoisting
Variable hoisting and function hoisting occur in JavaScript. This means that it doesn’t matter where you define the variable or function, within the scope that you’re using it in, it is always available immediately. In the case of variables, the assignment is not available until the location that it occurs, but the variable reference is. Named functions are available to be used immediately, no matter where they occur in the scope.
Due to hoisting nature, there are some gotchas with function expressions assigned to variables. A function expressions assigned to a variable, will have the variable hoisted, but not the function. So, the “typeof” the function variable is essentially undefined. An actual *named* function on the other hand is hoisted to the top, along with it’s declaration, making it immediately available for use. (3) p.g 61
console.log(typeof a); // undefined and unusable as a function console.log(typeof b); // function var a = function() { console.log('hello a'); } function b() { console.log('hello b'); } |
Local Scope
It’s important to note that local scope cannot be created just by blocks. e.g. { var myVar; } doesn’t make myVar local if it’s defined in the parent scope. You have to create a function, or a function expression (otherwise known as a closure). (3) p.g. 58
Functions
If you have an object with a function, and you pass that function by reference to another function, when it is called the *this* keyword will not reference the parent object. It will instead reference the global object, or will be undefined if “use strict” is in use. An example snippet is below.
var myObject = { doSomething: function () { console.log(this); // global object or undefined in call below; NOT myObject } } function doThis(callback) { callback(); } // should result in displaying the window object, if pasted // into a javascript browser console. doThis(myObject.doSomething); |
Sources:
(1) W3C Schools
(2) Java Script Pocket Reference (3rd Edition) by David Flanagan
(3) Java Script Patterns by Stoyan Stefanov