Object JavaScript – Scope, Namespaces, “use strict”

10063_580983808600819_401360548_nIn this post, you will learn about how JavaScript defines scopes and how you can use that to your advantage by declaring your own namespaces. Namespaces help you lower the possibility of naming collisions when using our code in conjunction with other JavaScript libraries.

Scope

Many modern programming languages, such as C, C++, C#, Objective C all have the idea of scope.

Scoping helps you prevent naming collisions, where you may write a function that contains a variable name that might be used in a different way in another part of the application. In JavaScript two regions of your code may use the same global variable name. A global variable is on that can exist outside of a function or object.

JavaScript exposes the variables globally so that an inline script on your Web page or a script in an external file so each can access the variable, no matter where it is needed. When a global function or variable is created, it lives in the global namespace.

For example, you can have a global variable called myName and then used in a function called greeting.

myName = "Bruce";
function greeting() {
  return "Hello " + myName;
}

And you can declare a variable, such as hello, that is inside your function. That variable lives inside of the greeting() function only.

myName = "Bruce";
function greeting() {
  var hello = "Hello there ";
  return hello + myName;
}

So, JavaScript does have function-level scoping, so when you declare a variable or function using var keyword, the value you declare is valid only within the function.

But this can still get confusing when you use the name of a variable inside a function and outside a function.

For example,


var two;
two = 2;
three = 3;
incrementValues();
console.log("two after increment = " + two + "\n");
console.log("three after increment = " + three + "\n");
function incrementValues() {
var two;
two = 2 + 1;
three = 3 + 1;
console.log("incremented two = " + two + "\n");
console.log("incremented three = " + three + "\n\n");
}

view raw

ojs-twotwos.js

hosted with ❤ by GitHub

The code produces:

incremented two = 3
incremented three = 4

two after increment = 2
three after increment = 4

This example demonstrates two sets variables. One set introduced outside the incrementValues() function, and one set inside the function. Names of variables in one set collide with the other set. The variable three becomes an implicit global variable that is accessed in and outside of the function. The variable two is a global when it is declared and a local variable inside the incrementValues() function.

But if you have an application that has functions or a variable defined with the same name in multiple locations, the last one loaded wins. So any code that uses the first variable may well not work as expected.

Strict Mode

The fifth edition of the ECMAScript specification introduced Strict Mode. Strict mode is a way to introduce better error-checking into your code, and will help with some of the issues listed in the previous section.

Among other things, when you use strict mode, you cannot:

  • accidentally create global variables or use implicitly declared variables.
  • assign a value to a read-only property.
  • add a property to an object that is not extensible.

Adding “use strict” as the first statement in your JavaScript code will enforce Strict Mode over the entire source.

Here are some examples:


"use strict";
mistypedVariable = 17; // throws a ReferenceError
// Assignment to a non-writable property
var obj1 = {};
Object.defineProperty(obj1, "x", { value: 42, writable: false });
obj1.x = 9; // throws a TypeError
// Assignment to a getter-only property
var obj2 = { get x() { return 17; } };
obj2.x = 5; // throws a TypeError
// Assignment to a new property on a non-extensible object
var fixed = {};
Object.preventExtensions(fixed);
fixed.newProp = "ohai"; // throws a TypeError
delete Object.prototype; // throws a TypeError
var o = { p: 1, p: 2 }; // !!! syntax error
function sum(a, a, c){ // !!! syntax error
"use strict";
return a + b + c; // wrong if this code ran
}

Strict mode isn’t a subset of JavaScript: it intentionally has different semantics from normal code. Browsers not supporting strict mode will run strict mode code with different behavior from browsers that do, so don’t rely on strict mode without feature-testing for support for the relevant aspects of strict mode.

Strict mode code and non-strict mode code can coexist, so scripts can opt into strict mode incrementally.

For a list of key restrictions that Strict Mode adds, see Strict Mode (JavaScript).

Namespace

You can reduce the number of objects and functions that are added to the global scope in our applications by using namespaces. In JavaScript, namespaces don’t have any dedicated syntax built in. But you can get the same benefits by creating a single global object and adding all your objects and functions to this object.

The simplest way to create a namespace is to use an object literal.


var myApp = {};
myApp.name = "Spock";
myApp.greeting = function() {
return "Hello " + myApp.name;
}

Or you can use a different syntax.


var myApp = {
name: "Bruce";
greeting: function() {
return "Hello " + myApp.name;
}
};

This approach is better that having outright global variables for name and greeting. Yet it still exposes everything within the namespace as global — both myApp.name and myApp.greeting are available everywhere. And inside the greeting function, you need to use myApp.name rather than just name.


var myApp= (function(){
// Create a private variable
var name = "Bruce";
// Create a private function
var greeting = function() {
return "Hello " + name;
};
// Return an object that exposes our greeting function publicly
return {
greetings: greeting
};
})();

When the function is executed a private variable name and a private inner function greeting are created. The inner function can refer to the private variable name directly. The main function then returns an object literal containing a reference to the greeting private function – which then exposes the greetings as a public function so we can call from the myApp namespace.

console.log(myApp.greetings());

However, this approach can become very cumbersome and hard to maintain when our code expands over time. In order to overcome this issue we can use a general purpose namespace function to achieve the same thing using a single line of code.


var your_namespace = your_namespace || {};

JQuery’s global $

As a general rule, “global” objects are stored inside the jQuery namespace as well, so you shouldn’t get a clash between jQuery and any other library (like Prototype, MooTools, or YUI).

One variable that can collide is $. By default, jQuery uses “$” as a shortcut for the “jQuery” object.

If another library uses $, you can override that default by calling jQuery.noConflict. See Using jQuery with Other Libraries for details.

References