Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Javascript

JavaScript Jargon

4.94/5 (56 votes)
8 Sep 2011CPOL8 min read 91.3K  
A selection of JavaScript terminology, with explanations and code samples

Introduction

Coming to JavaScript from C#, I came across some new terminology, as you would expect. Here I'll run through some of those new terms, with some examples of what exactly they're about. Some of them aren't really "new" terms, but have different or special meanings, and that warrants their inclusion here.

Contents

Anonymous

Anonymous functions are those with no name.

As I've said before, the ECMAScript specification does not have any mention of the term anonymous, so in a sense it is open to interpretation. However, there is a clear consensus from the JavaScript community on the "no name" definition - with sources including Crockford, Mozilla, the Chrome debugger and Firebug.

So, for the avoidance of doubt, this is an anonymous function. It is assigned to variable func, and so forms a "function expression": 

JavaScript
var func = function(){
    ...
};

In this next case, the function is not anonymous because it has a name. Also, because it isn't assigned to a variable it forms a "function declaration":

JavaScript
function func(){
    ...
} 

Now, both of these options will result in a function being defined, and available via an identifier named 'func'. So in both cases, we can call it normally:

JavaScript
func();

In practical terms, what is the effect of an anonymous function? The answer is: brevity, and that's it. You should normally give each function a name to ensure that during debugging, you can see its name in the call stack.

Closure

Closures are a central concept of JavaScript and should be one of the first things that a JavaScript programmer learns. They can be very powerful and will allow us to emulate many patterns from other programming languages.

A closure is a functional scope (a set of variables) which is kept alive after the function returns.

To put that another way, through the cunning use of an inner function, we can keep a reference to the variables in its outer function - even after the outer function returns. So, a quick example:

JavaScript
function outerFunc(){
    var name = "bob";

    return function innerFunc(){
        alert("hello " + name);
    };
}

// Execute outerFunc which returns innerFunc
var test = outerFunc(); 

// Execute innerFunc, and even though outerFunc has already exited, 
// its local vars are still in memory (name = 'bob')
test(); // 'hello bob'

Now, here we have a more practical example. JavaScript doesn't have private variables. However, we can create the concept of privacy by embedding private variables in a closure - and only functions inside the closure will have access to them. This is how it works:

JavaScript
function carFactory(make, model) {
    // private vars
    var count = 0;

    // private functions
    function isBatteryDead() {
        return true;
    }
    
    // public vars and functions - wrapped up in an object and returned
    return {
        make: make,
        model: model,
        start: function start(){
            if(!isBatteryDead()) {
                count++; //Increment this private variable
            }
        }
    };
}
// Create a car
var fordFiesta = carFactory('ford', 'fiesta');
fordFiesta.start();

This is a powerful way to create private members, but unfortunately the downside is that each time the carFactory is used to create a car, a brand new copy of the member functions is created - instead of re-using the functions as we would be used to in C#. We can do that, however, using prototypes, explained later.

Note that returning the inner function isn't the only way to create a closure; all we need to do is to keep the scope alive after the outer function returns. Here are some more ways that can happen.

Example 1 - with setTimeout

JavaScript
function outerFunc(){
    var name = "bob";
    setTimeout(function(){
        alert(name);  //Happens second
    }, 0);
}
outerFunc();
alert("hello");  //Happens first

The output of the code above is an alert of "hello" followed by an alert of "bob". So even after the outerFunc exits, we see an alert of a variable inside it.

Example 2 - assigning to an outer scope

JavaScript
var ref;
function outerFunc(){
    var name = "bob";
    ref = function innerFunc(){
        alert(name);
    };
}
outerFunc();
ref(); 

This one might look a bit complicated, but it's not really. We are simply creating a variable called 'ref' which will reference the inner function. When the outer function executes, it assigns the inner function to that 'ref' variable, then returns. Then we can look at our 'ref' variable to access the inner function, along with the variables in its scope.

Currying

Currying is a technique whereby a function with multiple arguments is converted to a function with fewer arguments. You would do this in a situation where you already know the value of one or more of the arguments, and you'd like to get a function that only takes the arguments you don't already know - so you don't have to continually keep passing in the same arguments when calling it. This is made easy in JavaScript with its functions being first-class citizens that can be simply passed around at will.

Let's assume we've got a normal function that takes a number of arguments, such as this jQuery function that sets an attribute:

JavaScript
function attr(key, value) {
	// Sets an attribute on some element
}

jQuery("#bob").attr("title", "this is the title");

Currying would involve doing the following, which is to wrap the attr function in a new function with fewer arguments, and allows us to fix the values of two of the arguments (the jQuery object and the name of the attribute)

JavaScript
function getAttrFn(elem, key) {
	return function(value){
		elem.attr(key, value);
	};
}

The above getAttrFn works because we create a closure in which the element and key is stored until the returned function is executed. It is used like this:

JavaScript
var setTitle = getAttrFn(jQuery("#bob"), "title");
setTitle("this is the title"); // Sets the title of element #bob

One use of this technique would be to create an event handler function that matches the signature required, while passing other useful parameters to an existing function.

One downside, however, is that if used very frequently then a performance hit might be noticed - we are, after all, adding an extra function call to the stack each time we curry.

Hoisting

Variable Hoisting

Hoisting is when the JavaScript runtime does wacky things with your variables, by effectively moving the line on which they are declared. This helps to explain why (and how) there is no block scope, only function scope - because the variable declaration is "hoisted" up to the beginning of the function.

So, for example, we can observe the following phenomenon:

JavaScript
1. var a = 1;
2. function hello() {
3. 	alert(a);  // undefined (not 1!)
4. 	var a = 2;
5. 	alert(a);  // 2
6. }

In this example, the variables defined within function "hello" are defined at the top of the function, i.e., line 3. The interpreter in essence executes this code:

JavaScript
1. var a = 1;
2. function hello() {
3.	var a = undefined;
3. 	alert(a);  // undefined (not 1!)
4. 	a = 2;
5. 	alert(a);  // 2
6. }

The variable a is hoisted to the top of the function. This is why in JavaScript, we should always try to declare variables at the start of the function so that this behaviour becomes obvious. JSLint enforces this.

Here is one other example which is also a little confusing, a for loop:

JavaScript
function hello() {
	for (var i=0; i<10; i++) {
		// i = 0 to 9
	}
	alert(i); //10
}

This occurs for the same reason, that variable i is hoisted to the top of the function instead of being scoped only within the for loop.

Functional Hoisting

The hoisting of functions is similar, but not the same since there is a small distinction between function expressions and function declarations. Function expressions follow the same hoisting rules as variables:

JavaScript
expression(); // undefined
var expression = function() {
	console.log("hello");
};

...while function declarations are fully hoisted to the top - in other words, they are available right from the beginning of their outer function.

JavaScript
declaration(); // hello
function declaration() {
	console.log("hello");
}

Type Coercion

Type coercion is the conversion of one data type to another. This should normally be avoided in JavaScript (double-equals forces type coercion, leading to strange effects; triple-equals does not perform any conversion and so is type-safe - this is much simpler and easy to understand).

The exception to this generalisation is when coercing to a Boolean. This is because any value in JavaScript is either 'falsy' or 'truthy' - meaning it can be coerced to a boolean to use as a conditional in an if statement, for example. Here are a list of the truthy values - everything else is falsy:

  • True
  • Numbers not equal to 0
  • Non-empty strings
  • Objects (even those without any properties)
  • Functions

You can test whether a variable is truthy or falsy in the debugger by using !!, e.g.:

JavaScript
var a = 0;
console.log(!!a); // false

The innermost exclamation mark coerces the value to a Boolean and gets its opposite. The outermost exclamation mark then reverses that.

Alternatively, you can more explicitly convert to a Boolean:

JavaScript
var a = 0;
console.log(Boolean(a)); //false

Scope

Scope is in this article because scope is always functional. There is no separate block scope for loops of any kind, if statements, etc. Wherever a variable is declared, its declaration (but not assignment) is hoisted to the top of its function. However, due to the existence of closures, the scope is not necessarily the innermost function. For further explanation, go back to Closure and Hoisting!

If you wish to create a separate scope, you can create a self-executing function.

Self-executing Function

A self-executing function is one that is both defined and called all at once. This is useful when you want to create a "block scope" - variables defined in it are not available outside it. Also, due to closure, it can see variables defined outside - the same as a block scope in other languages.

JavaScript
(function(){
	var x = "hello";
}());

console.log(x); // undefined

This

In C# (and most object oriented languages), this refers to the current object. However in JavaScript, this refers simply to the object on which a function has been invoked. If the function isn't invoked on any object, then this refers to the window object (which is perfectly natural - after all, functions are first-class objects themselves and don't require an 'owner' object).

Example 1 - global scope

JavaScript
function whatIsThis(){
	console.log(this);
}
whatIsThis(); // Window (global scope)

Example 2 - function declared as an object property

JavaScript
var obj = { 
	whatIsThis: function(){ 
		console.log(this);
	}
};
obj.whatIsThis(); // obj

Example 3 - invoke a function on an arbitrary object

JavaScript
var obj = { };
function whatIsThis(){
	console.log(this);
}
whatIsThis.call(obj); // obj

Prototype

JavaScript is a classless object oriented language. But if it's classless, then how do we define what objects should look like? The answer is prototypes. A prototype is an object that is assigned to the 'prototype' property of a function. Then that function can be used as a constructor, and the prototype becomes a model of how the resulting object will behave.

JavaScript
var Vehicle = function () {
	...
};
Vehicle.prototype = {
	started: false,
	start: function(){ 
		//do stuff
	}
};

var c = new Vehicle();

Use of the new operator before a function call does a number of things:

  • An new, empty object is created
  • The new object is pointed towards the prototype
  • The function is executed with the object as its context ('this' points to it)
  • The object is returned

Additionally, an inheritance pattern can be created by copying the "base" prototype to the "super" object.

For example, let's say Vehicle is the base type (I'm working hard to avoid using the word class!) and Car should inherit from it, we assign an instance of Vehicle to Car's prototype:

JavaScript
var Car = function(){
	...
};
Car.prototype = new Vehicle();

Now that we've got the Car set up, we can extend it by adding some additional functions to its prototype:

JavaScript
Car.prototype.OpenSunroof = function() { ... };

There are many, many ways to implement classical inheritance in JavaScript, but this technique of prototypical inheritance should illustrate how prototypes are used.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)