Now JavaScript is more than just Web page effect script, more used to build large-scale Web applications, so the language specification of the developers are gradually aware of the syntax of JS to standardize, and deliberately guide the developer programming habits, eliminate some non-standard and unsafe syntax, In order to better meet the requirements of large-scale development later, the strict mode of ES5 specification is one of the important link, today we will introduce in detail the use of strict mode and its various restrictions and norms of grammar.
Enable strict mode only using ' use strict '; This statement, in the case of a browser that supports strict mode, declares ' use strict '; The code after the statement will be enforced under strict mode, for browsers that do not support strict mode, this declaration is just a simple string statement without any effect, and the code we write in strict mode is canonical and can run well, so there is no need to worry about compatibility. Here is a simple declaration of strict mode:
' Use strict '; Console.log ("I-m running in strict mode");
It is important to note that strict mode declarations must be placed on the first line of the script, or the entire script will run in normal mode.
Strict mode is applied in two scopes, one is the entire script scope, one is a single function scope, and the script scope is first described below:
<script type= "Text/javascript" > ' use strict '; Console.log (' Strict mode comes into effect. '); </script><script type= "Text/javascript" > console.log ("strict mode doesn ' t take control of me."); </script>
Above we used two script tags, inside the first label we declared the strict mode, the second one does not, the result will be, strict mode only in the first tag inside the function, the second label inside the script will run in normal mode. If the script tag above refers to the external JS file, the result will be consistent. It is important to note that strict mode is used in a single script, especially when merging files, with the strict mode of the previous file having an unpredictable effect on the next file.
Strict mode can also be declared within a single function, in which case the strict pattern only works on code within the function:
function A () { ' use strict '; Console.log ("I ' m running in strict mode"); Function B () { console.log ("I ' m also in strict mode");} } Console.log (' Strict mode takes no effect here ');
It is relatively safe to enable strict mode within the scope of the function, so considering the merging of files in our development, it is best to put each script file inside the immediate execution function, and there is no worry about declaring strict mode inside this function:
;(function () { ' use strict '; Console.log ("I ' m running in strict mode"); Function B () { console.log ("I ' m also in strict mode"); }}) ();
Here we introduce a small episode of why we want to add a semicolon to the immediate execution of the function. If there are two files: A.js and B.js, they are merged together at the time of publication:
var baseplus = function (basenumber) { return function (number) { Console.log (basenumber + number);} } (function (name) { console.log (' hello ' + name);}) (' Scott ');
In the above code, the Baseplus function is defined without a semicolon, so this code is interpreted as:
var baseplus = function (basenumber) { return function (number) { Console.log (basenumber + number);} } (function (name) { console.log (' hello ' + name);}) (' Scott ');
As a result, the following immediate execution function did not achieve the desired effect, but the function inside was passed into the Baseplus function as a parameter, and Scott passed it as a parameter to the function returned by baseplus, printing the result as follows:
So, here we're going to add a semicolon to the immediate execution of the function, even if it's stitched together like this:
var baseplus = function (basenumber) { return function (number) { Console.log (basenumber + number) }};( function (name) { console.log (' hello ' + name);}) (' Scott ');
Here are two scenarios for declaring strict patterns, and then we'll show you what the strict patterns do:
1. Variables must be declared with Var to avoid accidentally declaring local variables as a global variable
In normal mode, if we omit the var keyword when declaring a variable, the parsing engine automatically declares it as a global variable, but in strict mode it throws an exception and does not convert us to a global variable:
' Use strict '; myvariable = 3;//uncaught referenceerror:myvariable are not defined
2. An error is displayed on an operation that exceeds the permission, and no more silent failures are processed
In normal mode, we can do a lot of illegal operations, such as assigning Nan a value, Nan is a non-writable variable, but we try to update it without receiving any error feedback information, strict mode is different, it will show the throw exception, here are some illegal operations:
' Use strict '; NaN = 3; Uncaught TypeError: var = {};object.defineproperty (person, ' name ', { writable:false, value: ') Scott '});p erson.name = ' John '; Uncaught TypeError: var person2 = { Get name () { return ' Scott '} };p erson2.name = ' John ';//uncaught Type Error: var person3 = { name: ' Scott '};object.preventextensions (person3);p erson3.age =;//uncaught TypeError: ...
In the previous blog, about the enhancement of object we also introduced a lot of illegal operation in the strict mode of operation State, students can also go to see.
3. Prohibit deletion of variables and objects in the non-deleted properties, display error
As we all know, variables declared through Var are not to be deleted, in general mode, attempts to delete silently fail, but in strict mode the exception is thrown explicitly, and the attempt to delete non-deleted properties in the object also explicitly error:
' Use strict '; var myvariable = 3;delete myvariable; Uncaught syntaxerror:.. delete Object.prototype; Uncaught TypeError: var = {};object.defineproperty (person, ' name ', { configurable:false, value: ') Scott '});d elete person.name; Uncaught TypeError: ...
4. Prohibit object property names
In general mode, if we define duplicate properties in an object, then the defined value overrides the one defined first, and the strict mode of ES5 specifies that duplicate attributes are not allowed in the object, otherwise they will be explicitly error-marked. However, bloggers found in the test that the code in strict mode is not the same as the regular mode, because Chrome supports a subset of the ES6 new features, and ES6 has a related bug:bug 1041128.
' Use strict ';//it should throw a syntaxerror in ES5 strict modevar person = { name: ' Scott ' name: ' John '};console. Log (person.name);
5. Disable duplicate function parameters
In general mode, if you accidentally declare a duplicate parameter name in the definition function, the latter parameter overrides the previous duplicate parameter, although arguments can access each parameter value, but sometimes it also encounters unexpected results:
var b = 0;function sum (A, A, c) { return a + B + C;} Console.log (SUM (1, 2, 3)); 5
In the above code, we accidentally write parameter name B as a, there happens to be a variable b in the outer layer, so the result of the operation becomes unpredictable, and the result is that argument 2 overrides the argument 1, 2 + 0 + 3 = 5. This problem is well avoided in strict mode, because strict mode constrains the definition of functions at the syntactic level, and does not allow for the repetition of parameter names:
' Use strict '; var b = 0;function sum (A, A, c) {//uncaught SyntaxError: ... Return a + B + C;} Console.log (SUM (1, 2, 3));
6. Prohibit the use of octal digits
Octal numbers starting with 0 are often confusing to developers, and strict mode prohibits the eight-mechanism notation that begins with 0, and ES6 already supports the new syntax standard, which is represented by octal in 0o, which forms a uniform syntax format with 16 binary 0x:
' Use strict '; var a = 017; Uncaught syntaxerror: ... var b = 0o17; ES6 octal Syntax:8 + 7 = 15
7. Prohibit the use of with statements
The mood when you first use the WITH statement is exciting, because the WITH statement takes the specified object as the current scope and can access the object's properties very directly, making our code more concise. But at the same time it is problematic, because the parser in the execution of the code inside, it will check whether there is an object to participate in the operation of the property, if there is the use, if not, then look up, this process to some extent, reduce the performance of code execution, and difficult to optimize, in addition, in terms of readability is very poor, Let's look at the following code:
var name = ' Scott '; var person = Getperson (); with (person) { name = NewName;}
In the above code, it is difficult to determine the person object before the code runs, so it is unclear whether the WITH statement will change the name variable or the Name property of the person as defined above. In order to standardize this behavior, strict mode prohibits the use of the WITH statement and, if used, throws an exception immediately:
' Use strict '; var name = ' Scott ', var person = Getperson (), with (person) { //uncaught syntaxerror: ... name = NewName;}
8. Force a new scope to be created for Eval
In general mode, using the Eval function may affect the current scope or global scope, which brings uncertainty to the running results of the program, and strict mode creates a third scope for the JavaScript program: the eval scope. The strings in the Eval function can only run within the eval scope, and the result does not affect the outer scope, both of which allow Eval to run in strict mode:
' Use strict '; eval ("var a = 1;"); Console.log (a); Uncaught referenceerror:a is not a defined//oreval ("' Use strict '; var b = 3; "); Console.log (b); Uncaught REFERENCEERROR:B is not defined
As you can see, executing the eval function in strict mode does not affect the current scope. It is important to note that if you do not execute the Eval function directly, you will not enter strict mode, and the following methods do not execute the Eval function code in strict mode:
' Use strict ';(' | | Eval) ("var a = 1;"); or (", eval) Console.log (a); 1var EVL = EVAL;EVL ("var b = 3;"); Console.log (b); 3function EXEC (EVL) { EVL (' var c = 5; '); Console.log (c); 5}exec (eval);
We also see, although the strict mode is declared, but a few results are different from the regular model, which we should pay special attention in the development, can not be thought to declare the strict mode can be assured to write code, the hidden dangers lurking in it.
Finally, you might ask, if you want to use the Eval function in strict mode to process a string, how to reflect the result to the current scope, we need to look like this:
' Use strict '; var result = eval ("var sum = 1 + 3 + 5; sum; "); Console.log (result); 9
9. Prohibit illegal operation of Eval and arguments
The general mode of JavaScript in the randomness of the larger, eval and arguments can have a lot of strange usage, although the program can run, but this to the readability of the code, maintainability also brings some problems, the following code snippets should be avoided as far as possible:
function eval () { Console.log (' Define a function called eval ');}; Console.log (eval), function Evalx (eval) { Console.log (' Define a function with the Eval keyword as parameter name ');} Console.log (evalx); function arguments () { Console.log (' Define a function called arguments ');}; Console.log (arguments); var func = new Function (' arguments ', ' return 3; '); Console.log (func); var eval = 1;console.log (++eval); 2var arguments = 3;console.log (++arguments); 4var person = { set name (arguments) { console.log (arguments);//scott }};p erson.name = ' Scott '; try { Console.log (unknownvariable);} catch (arguments) { console.log (arguments);//referenceerror:unknownvariable is not defined}
In strict mode, the interpreter disables Eval and arguments at the syntactic level, and once the strict schema is declared, these operations will throw a syntax exception directly. It is important to note that Eval simply cannot be used as a function parameter name when defining a function, it can be passed in as an argument when calling a function, which is reflected in 8th, and in this form of creating a function using the new function, we declare that strict mode is invalid in the outer layer, Strict patterns must be explicitly declared inside the function body, with the following code:
' Use strict '; Strict mode is beyond the controlvar func = new Function (' arguments ', "return 3;"); Console.log (func);//declaring the ' use strict ' function body is a mustvar func = new function (' arguments ', "' use strict '; return 3; "); Console.log (func);
arguments no longer tracking parameter changes
In general mode, if we change the value of a parameter when executing a function, the result of the operation is immediately reflected in the arguments object, and conversely, the value in the arguments object is changed, and the result is immediately reflected on the parameter:
var fn = function (A, B, c) { a = ten; Console.log (Arguments[0]); Ten arguments[1] =; Console.log (b); 20};FN (1, 2, 3);
Strict mode constrains this behavior, separates arguments objects from parameters, changes only affect themselves, does not affect each other, in strict mode, the result of the above operation is as follows:
' Use strict '; var fn = function (A, B, c) { a = ten; Console.log (Arguments[0]); 1 arguments[1] =; Console.log (b); 2};FN (1, 2, 3);
11. Prohibit the use of Arguments.callee
Callee as a property of the arguments object, we can call it inside the function to get the currently executing function, which is especially useful in some scenarios, especially in anonymous recursive functions. If we have an array, we now need to find the factorial for each element in the arrays, perhaps as in the following code:
var factorialarray = [1, 2, 3, 4, 5].map (function (n) { return (n < 2)? 1:arguments.callee (n-1) * n;}); Console.log (Factorialarray); [1, 2, 6, 24, 120]
We use the array new function map to process the arrays, call the anonymous function for each array element to the factorial, here we use the Arguments.callee to get the current execution of the anonymous function, and then recursively called, and finally to the factorial value of each element.
So why is strict mode forbidden to Arguments.callee, one of the reasons is that it cannot be optimized for inline and tail recursion. In the following code we use a for loop to find the factorial of each value in the loop:
function getfactorial (n) { return (n < 2)? 1:arguments.callee (n-1) * N;} function calculate () {for (var i = 0; i <; i++) { Console.log (getfactorial (i));} }
Because every time the getfactorial function is called, the function that is currently being called is found inside it, so the parser can do inline processing to improve the performance of the Getfactorial function, and now uses the callee, which greatly affects the parser's optimization strategy. The following code is an example of a tail-recursion:
function factorial (n, result) { if (n < 2) return result; return factorial (n-1, n * result); Console.log (Factorial (5, 1));
We see that this recursive and regular recursion is different, each time it calls itself with the result of the last call, the parser will be optimized for this code, the optimized code runtime no longer occupy too much stack, each time only the call record of the inner function, save memory, and there is no memory overflow situation.
But if we use Arguments.callee in the recursion above, the situation is different:
function factorial (n, result) { if (n < 2) return result; Return Arguments.callee (n-1, n * result); Console.log (Factorial (5, 1));
This code, although the result is the same, but the parser can not optimize it, because arguments saved the function call stack information, parser optimization can not arbitrarily modify the stack information, so will abandon the optimization of this piece of code.
The above is the optimization of the inline and tail recursion, in fact, there is a very important reason, that is, using Arguments.callee will change the function in the direction of this:
function factorial (n, result) { console.log (this); if (n < 2) return result; Return Arguments.callee (n-1, n * result); Console.log (Factorial (5, 1));
We print the context object that the function is currently executing in the code, and the result is as follows:
As you can see, in a call that uses Arguments.callee, except for the first external call, this is the arguments object, and if the function references the current context, it also creates uncertainty about the result of the program.
Therefore, the use of Arguments.callee calls is forbidden in strict mode, and if strict mode is declared, encountering Arguments.callee throws an exception.
Finally, if you can't use Arguments.callee, how do you call yourself in an anonymous function? Starting from ES3 The name function expression is introduced into the language feature, so we can use it just like the following code:
var factorialarray = [1, 2, 3, 4, 5].map (function factorial (n) { return (n < 2)? 1:factorial (n-1) * n;}); Console.log (Factorialarray); [1, 2, 6, 24, 120]
Using a named function expression can also call itself inside a function, and in modern browsers it is not possible to create a variable in an external scope, and the performance is much better than using arguments, so it is recommended.
12. Prohibit this from pointing to the global
In general mode, JavaScript is too flexible, if the language features are not well understood, often due to the wrong call, resulting in inconsistent results, the following program demonstrates the point of this problem:
var name = ' Global '; function person () { this.name = ' Scott ';} Person (); Console.log (name); Scottvar person = { name: ' John ', getname:function () { return this.name; }}; var getName = Person.getname;console.log (GetName ()); Scott
We first define the person constructor, which sets its member variables, but then does not use new to create an instance, but instead calls the function directly, and the result is that this execution of the function points to the global, so the global name variable is changed to Scott In the following person object we define the Name property and the GetName function, but later we call this function indirectly, the function of this also points to the global, the result does not return the person's Name property value, but the global most recent name variable value Scott. It is a very dangerous operation to allow this to point to the global in general mode.
In strict mode, this is not allowed to point to the global, and if the runtime tries to point to the global, this will become undefined, and the code in strict mode calls the person function will throw an exception because the property cannot be set for undefined. We can test it with the following code:
' Use strict '; var func = function () { return this;}; Console.log (func () = = = undefined); True
In addition, in general mode, this is always an object, even if the runtime context is the underlying type, and is automatically boxed as an object:
var func = function () { return this;}; Console.log (Func.call (' Hello ')); Boxed Stringconsole.log (Func.call (1)); Boxed Numberconsole.log (Func.call (true)); Boxed Booleanconsole.log (func.apply (null)); Windowconsole.log (func.apply (undefined)); Window
In strict mode, the automatic boxing mechanism is no longer available, and the performance is greatly improved:
' Use strict '; var func = function () { return this;}; Console.log (Func.call (' hello ') = = = ' Hello '); Trueconsole.log (Func.call (1) = = = 1); Trueconsole.log (Func.bind (True) () = = = True); Trueconsole.log (func.apply (null) = = = null); Trueconsole.log (func.call (undefined) = = = undefined); True
We can easily see that the types they have before and after are exactly the same.
13. Prohibit direct referencing of caller and arguments using function
As we have just described above, the usage of Arguments.callee is forbidden in strict mode, and as a result of the performance and security considerations, Strict mode prohibits direct access to the function's call stack information through the functional name, so the following code throws an exception directly:
function TestFunc () { ' use strict '; Console.log (Testfunc.caller); Uncaught TypeError: ... Console.log (testfunc.arguments); Uncaught TypeError: ...} function Main () { testFunc ();} Main ();
14. Functions must be declared at the entire script or function level
In general mode, declaring a function in a statement block makes the result of the program unpredictable and makes readability worse, and the following code will have different results in different browsers:
var condition = true;if (condition) { function dosomething () { console.log (' 1 ');} } else { function DoSomething () { console.log (' 2 ');} } DoSomething ();
On Mac platforms, Chrome and Firefox will choose the corresponding function based on the value of condition, and Safari will ignore condition, directly using the function defined later, so the result will always print 2. This scene is the gray area in the ECMAScript and should be avoided as much as possible.
Strict mode prohibits declaring a function in a statement block, the following code does not throw a syntax exception when it is tested in chrome, but ignores the declaration of the DoSomething function, with the result that an exception is thrown when calling DoSomething, suggesting that the function is undefined:
' Use strict ', if (true) { function dosomething () { console.log (' 1 '); }} else { function dosomething () { C4/>console.log (' 2 ');} } for (var i = 0; i < 5; i++) { function dosomething () { console.log (' 3 '); }} DoSomething (); Uncaught referenceerror:dosomething is not defined
Therefore, you should not declare the function in the block statement, but at the script and function level.
15. Add some reserved words
ES5 is essentially a language-optimized transition that constrains obscure and unsafe syntax and paves the way for later advanced syntax. So there are some new reserved words in ES5, in strict mode, they cannot be used as variable or parameter names:
Implements, interface, let, package, private, protected, public, static, yield.
The above is the ES5 strict mode of the entire content, if there are omissions or inconsistencies, and then supplemented.
Strict mode of ES5 specification