Saturday, February 15, 2014

JavaScript Best Practices : ECMAScript 5 Strict Mode

JavaScript allows developer to do tricks which many other languages do not allow to code. This behavior of JavaScript sometime causes some confusion in JavaScript code and unexpected behaviors. To overcome this in ECMAScript 5 has introduced Strict mode which is supported with all latest browsers and also do not conflict with old browsers.

What Strict Mode is?

Strict Mode is a new feature that allows developer to place code in a strict operating context which prevents certain ambiguous and confusing action from being taken and prompt with more information by throwing exception.

Strict mode gives advantage to developer in following ways:
  • Strict mode disabled the feature which are confusing.
  • Strict mode throws exception on coding mistakes.
  • Strict mode prevent developers by throwing exception if unsafe actions like accessing global object are being made
ES5 specification has detailed information about change in [PDF] or you can see here.


How strict mode works?

Simple. Toss this at the top of a program to enable it for the whole script:
Using strict mode is simple, to make complete script file in strict mode put at the top of script:
"use strict";

Or to make certain functions or context to be strict put the string in that context.
function myFunctionToBeStrict(){
"use strict";
// ... your code ...
}
Enabling strict mode is really a simple just put the string at the top of your any script and that is it. If browser support the strict mode it will start working, and old browsers working with ECMAScript 4 or previous will ignore it as string and keep working as they were.

You can work in dual mode by placing all of your code to execute in strict mode in a context and made that context strict. All the code outside of that context will works in non-strict mode.
// Non-strict context...

(function(){
"use strict";

// strict code context...
})();

// Non-strict context...

What Strict Mode prevents you to code?

Variables

If you try assignment to variable (e.g, myVar = "hello undeclared function";) which is not declared will throw exception. Previously it allows to assign and create a property to global object (e.g, window.myVar). This really prevents some unexpected situation to occur.

see demo here

myVar = "hello undeclared function";
alert("Without strict mode ::: " + myVar);

(function () {
 "use strict";

 try {
 testVar = "hello undeclared function";
 alert("With strict mode ::: " + testVar);
 } catch (ex) {
 alert("Strict mode Exception ::: " + ex);
 } 
})();

Properties

ECMAScript made properties more easily manageable and prevent some coding bloop causing unexpected behavior.

1- adding a property to an object whose extensible attribute is set to false.

see demo here

var myObj = new Object();
Object.preventExtensions(myObj);
myObj.name = "Smith";

console.log("without strict mode ::: "+ myObj.name);

(function () {
 "use strict";

 try {
 var strictObj = new Object();
 Object.preventExtensions(strictObj);
 strictObj.name = "Smith";
 console.log(strictObj.name);

 } catch (ex) {
 console.log("Strict mode Exception ::: " + ex);
 }
})();

2- Attempt to change a property value whose writable attribute is set to false.

see demo here

var myObj = new Object();

Object.defineProperty(myObj, "myVar", {
 value: 10,
 configurable: false
});

delete myObj.myVar;
console.log("Without Strict mode ::: " + myObj.myVar);

(function () {
 "use strict";

 try {
 var myStrictObj = new Object();

 Object.defineProperty(myStrictObj, "myVar", {
 value: 10,
 configurable: false
 });

 delete myObj.myVar;
 } catch (ex) {
 console.log("Strict mode Exception ::: " + ex);
}
})();
3- Try delete a property whose configurable attribute is set to false.

see demo here

var myObj = new Object();

Object.defineProperty(myObj, "myVar", {
 value: 10,
 configurable: false
});

delete myObj.myVar;
console.log("Without Strict mode ::: " + myObj.myVar);

(function () {
 "use strict";

 try {
 var myStrictObj = new Object();

 Object.defineProperty(myStrictObj, "myVar", {
 value: 10,
 configurable: false
 });

 delete myObj.myVar;
 } catch (ex) {
   console.log("Strict mode Exception ::: " + ex);
 }
})();
will result in an error . Previously there was no error when any of these actions are attempted, it will just fail silently.

Deleting variable, function, or argument

Deleting a variable, a function, or an argument will result in an error.
var myVar = "test";
function myFunc(){}

delete myVar; // Error
delete myFunct; // Error

function myFunc2(myArg) {
  delete myArg; // Error
}
In large objects where you defined multiple properties there is possibility of coding duplicate property. With ECMAScript 5 strict mode defining a property more than once in an object literal will cause an exception to be thrown.
// Error because prop1 is twice
var testObj = {
    prop1: 10,
    prop2: 15,
    prop1: 20
};

eval in Strict Mode

The string "eval" cannot be used as an identifier (variable or function name, parameter name, and so on).
// All generate errors...
obj.eval = ...
obj.foo = eval;
var eval = ...;
for ( var eval in ... ) {}
function eval(){}
function test(eval){}
function(eval){}
new Function("eval")
Adding new variable using eval is not allowed in strict mode.
eval("var addVar = false;");
console.log( typeof addVar ); // undefined

Functions in Strict Mode


Attempting to overwrite the arguments object within a function will result in an error(also Arguments as an identifier is not allowed):
function myArgs(myArg) {
    arguments[0] = 20; //not allowed
}
Defining two arguments of identical name is not allowed.
function myArgs(myArg,myArg) {
   //code
}
Access to arguments.caller and arguments.callee now throw an exception. Thus any anonymous functions that you want to reference will need to be named, like so:
function (testInt) {
    if (testInt-- == 0)
        return;
    arguments.callee(testInt--);
}
Defining and calling arguments and caller properties of function is not longer exist.
function myFunc(){
function myInnerFunc(){
// Don't exist, either
myFunc.arguments = ...; // Error
myInnerFunc.caller = ...; // Error
}
}


Eliminates this Coercion


Another important change is a this-value of null or undefined is no longer coerced to the global. Instead, this remains its original value, and so may cause some code depending on the coercion to break.


For example:


window.prop = "foo";
function sayProp() {
    alert(this.prop);
}

// Throws an error in strict mode, "foo" otherwise
sayProp();

// Throws an error in strict mode, "foo" otherwise
sayProp.call(null);
this value of any context must be assigned a value or else it remains undefined, so calling object without new keyword also throw error:
function Person(name) {
    this.name = name;
}

// Error in strict mode
var me = Person("Smith");
Since this is undefined causing error.

with(){}

with(){} statements are not usable when strict mode is enabled. It cause syntax errors.
with (location){
  alert(href);
}

No comments:

Post a Comment

Life insurance policy, bank loans, software, microsoft, facebook,mortgage,policy,