B

Strict Mode

ECMAScript 5 was the first to introduce the concept of strict mode. Strict mode allows you to opt-in to stricter checking for JavaScript error conditions either globally or locally within a single function. The advantage of strict mode is that you’ll be informed of errors earlier, so some of the ECMAScript quirks that cause programming errors will be caught immediately.

The rules of strict mode are important to understand, as the next version of ECMAScript will start with a base of strict mode. Strict mode is supported in Internet Explorer 10+, Firefox 4+, Safari 5.1+, and Chrome.

OPTING-IN

To opt-in to strict mode, use the strict mode pragma, which is simply a string that isn’t assigned to any variable:

"use strict";

Using this syntax, which is valid even in ECMAScript 3, allows seamless fallback for JavaScript engines that don’t support strict mode. The engines that support strict mode will enable it, while engines that don’t will simply ignore the pragma as an unassigned string literal.

When the pragma is applied globally, outside of a function, strict mode is enabled for the entire script. That means adding the pragma to a single script that is concatenated with other scripts into a single file puts all JavaScript in the file into strict mode.

You can also turn on strict mode within a function only, such as:

function doSomething(){
    "use strict";
 
    //other processing
}

If you don’t have complete control over all of the scripts on a page, then it’s advisable to enable strict mode only within specific functions for which it has been tested.

VARIABLES

How and when variables get created is different in strict mode. The first change disallows accidental creation of global variables. In nonstrict mode, the following creates a global variable:

//Variable is not declared
//Non-strict mode: creates a global
//Strict mode: Throws a ReferenceError
 
message = "Hello world!";

Even though message isn’t preceded by the var keyword and isn’t explicitly defined as a property of the global object, it is still automatically created as a global. In strict mode, assigning a value to an undeclared variable throws a ReferenceError when the code is executed.

A related change is the inability to call delete on a variable. Nonstrict mode allows this and may silently fail (returning false). In strict mode, an attempt to delete a variable causes an error:

//Deleting a variable
//Non-strict mode: Fails silently
//Strict mode: Throws a ReferenceError
 
var color = "red";
delete color;

Strict mode also imposes restrictions on variable names. Specifically, it disallows variables named implements, interface, let, package, private, protected, public, static, and yield. These are now reserved words that are intended for use in future ECMAScript editions. Any attempt to use these as variable names while in strict mode will result in a syntax error.

OBJECTS

In strict mode, object manipulation is more likely to throw errors than in nonstrict mode. Strict mode tends to throw errors in situations where nonstrict mode silently fails, increasing the likelihood of catching an error early on in development.

To begin, there are several cases where attempting to manipulate an object property will throw an error:

  • Assigning a value to a read-only property throws a TypeError.
  • Using delete on a nonconfigurable property throws a TypeError.
  • Attempting to add a property to a nonextensible object throws a TypeError.

Another restriction on objects has to do with declaring them via object literals. When using an object literal, property names must be unique. For instance:

//Two properties with the same name
//Non-strict mode: No error, second property wins
//Strict mode: Throws a syntax error
 
var person = {
                 name: "Nicholas",
                 name: "Greg"
             };

The object literal for person has two properties called name in this code. The second property is the one that ends up on person in nonstrict mode. In strict mode, this is a syntax error.

FUNCTIONS

First, strict mode requires that named function arguments be unique. Consider the following:

//Duplicate named arguments
//Non-strict mode: No error, only second argument works
//Strict mode: Throws a SyntaxError
 
function sum (num, num){
    //do something
}

In nonstrict mode, this function declaration doesn’t throw an error. You’ll be able to access the second num argument only by name while the first is accessible only through arguments.

The arguments object also has a slight behavior change in strict mode. In nonstrict mode, changes to a named argument are also reflected in the arguments object, whereas strict mode ensures that each are completely separate. For example:

//Change to named argument value
//Non-strict mode: Change is reflected in arguments
//Strict mode: Change is not reflected in arguments
 
function showValue(value){
    value = "Foo";
    alert(value);         //"Foo"
    alert(arguments[0]);  //Non-strict mode: "Foo"
                          //Strict mode: "Hi"
}
 
showValue("Hi");

In this code, the function showValue() has a single named argument called value. The function is called with an argument of "Hi", which is assigned to value. Inside the function, value is changed to "Foo". In nonstrict mode, this also changes the value in arguments[0], but in strict mode they are kept separate.

Another change is the elimination of arguments.callee and arguments.caller. In nonstrict mode, these refer to the function itself and the calling function, respectively. In strict mode, attempting to access either property throws a TypeError. For example:

//Attempt to access arguments.callee
//Non-strict mode: Works as expected
//Strict mode: Throws a TypeError
 
function factorial(num){
    if (num <= 1) {
        return 1;
    } else {
        return num * arguments.callee(num-1)
    }
}
 
var result = factorial(5); 

Similarly, the caller and arguments properties of a function now throw a TypeError when an attempt is made to read or write them. So in this example, attempts to access factorial.caller and factorial.callee would also throw an error.

Also, as with variables, strict mode imposes restrictions on function names, disallowing functions named implements, interface, let, package, private, protected, public, static, and yield.

The last change to functions is disallowing function declarations unless they are at the top level of a script or function. That means functions declared, for instance, in an if statement are now a syntax error:

//Function declaration in an if statement
//Non-strict mode: Function hoisted outside of if statement
//Strict mode: Throws a syntax error
 
if (true){
    function doSomething(){
        //...
    }
}

This syntax is tolerated on all browsers in nonstrict mode but will now throw a syntax error in strict mode.

EVAL()

The much-maligned eval() function receives an upgrade in strict mode. The biggest change to eval() is that it will no longer create variables or functions in the containing context. For example:

//eval() used to create a variable
//Non-strict mode: Alert displays 10
//Strict mode: Throws an ReferenceError when alert(x) is called
 
function doSomething(){
    eval("var x=10");
    alert(x);
}

When run in nonstrict mode, this code creates a local variable x in the function doSomething() and that value is then displayed using alert(). In strict mode, the call to eval() does not create the variable x inside of doSomething() and so the call to alert() throws a ReferenceError because x is undeclared.

Variables and functions can be declared inside of eval(), but they remain inside a special scope that is used while code is being evaluated and then destroyed once completed. So the following code works without any errors:

"use strict";
var result = eval("var x=10, y=11;  x+y");
alert(result);    //21

The variables x and y are declared inside of eval() and are added together before returning their value. The result variable then contains 21, the result of adding x and y, even though x and y no longer exist by the time alert() is called.

EVAL AND ARGUMENTS

Strict mode now explicitly disallows using eval and arguments as identifiers and manipulating their values. For example:

//Redefining eval and arguments as variables
//Non-strict mode: Okay, no error.
//Strict-mode: Throws syntax error
 
var eval = 10;
var arguments = "Hello world!";

In nonstrict mode, you can overwrite eval and assign arguments to a value. In strict mode, this causes a syntax error. You can’t use either as an identifier, which means all of the following use cases throw a syntax error:

  • Declaration using var
  • Assignment to another value
  • Attempts to change the contained value, such as using ++
  • Used as function names
  • Used as named function arguments
  • Used as exception name in try-catch statement

COERCION OF THIS

One of the biggest security issues, and indeed one of the most confusing aspects of JavaScript, is how the value of this is coerced in certain situations. When using the apply() or call() methods of a function, a null or undefined value is coerced to the global object in nonstrict mode. In strict mode, the this value for a function is always used as specified, regardless of the value. For example:

//Access a property
//Non-strict mode: Accesses the global property
//Strict mode: Throws an error because this is null
 
var color = "red";
 
function displayColor(){
    alert(this.color);
}
 
displayColor.call(null);

This code passes null to displayColor.call(), which in nonstrict mode means the this value of the function is the global object. The result is an alert displaying "red". In strict mode, the this value of the function is null, so it throws an error when attempting to access a property of a null object.

OTHER CHANGES

There are several other changes to strict mode of which you need to be aware. The first is the elimination of the with statement. The with statement changes how identifiers are resolved and has been removed from strict mode as a simplification. An attempt to use with in strict mode results in a syntax error.

//Use of the with statement
//Non-strict mode: Allowed
//Strict mode: Throws a syntax error
 
with(location){
    alert(href);
}

Strict mode also eliminates the octal literal from JavaScript. Octal literals begin with a zero and have traditionally been the source of many errors. An octal literal is now considered invalid syntax in strict mode.

//Use of octal literal
//Non-strict mode: value is 8.
//Strict mode: throws a syntax error.
 
var value = 010;

As mentioned in the book, ECMAScript 5 also changed parseInt() for nonstrict mode, where octal literals are now considered decimal literals with a leading zero. For example:

//Use of octal literal in parseInt()
//Non-strict mode: value is 8
//Strict mode: value is 10
 
var value = parseInt("010");
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.227.10.45