catalogue
2. Characteristics of strict mode
(2) Strict mode simplifies the use of variables
1, Strict mode overview
1. What is the strict model
Strict mode is a way to adopt restrictive JavaScript variants, so that the code implicitly deviates from the "sloppy / sloppy" mode.
Strict patterns are not just a subset: they are created to form semantics different from normal code.
Browsers that do not support strict mode and browsers that support strict mode behave differently when executing strict mode code.
Therefore, even if the strict mode is adopted, the expected effect may not be achieved without characteristic testing of the running environment to verify the support for relevant aspects of the strict mode. The strict mode code and non strict mode code can coexist, so the project script can gradually adopt the strict mode.
Strict mode makes some changes to the normal JavaScript semantics.
Note:
- The module of ES6 automatically adopts strict mode, whether you add "use strict" to the module header or not;.
2. Characteristics of strict mode
- Strict mode eliminates some of the original silent errors by throwing errors.
- Strict mode fixes some defects that make it difficult for the JavaScript engine to perform optimization: sometimes, the same code, strict mode can run faster than non strict mode.
- Strict mode disables some syntax that may be defined in future versions of ECMAScript.
3. Strict mode restrictions
Strict mode mainly has the following limitations:
- Variables must be declared before use
- The parameter of the function cannot have an attribute with the same name, otherwise an error will be reported
- The with statement cannot be used
- You cannot assign a value to the read-only attribute, otherwise an error will be reported
- The prefix 0 cannot be used to represent octal numbers, otherwise an error will be reported
- You cannot delete the undeletable attribute, otherwise an error will be reported
- The variable delete prop cannot be deleted and an error will be reported. Only the attribute delete global[prop] can be deleted
- eval does not introduce variables into its outer scope
- eval and arguments cannot be reassigned
- arguments does not automatically reflect changes in function parameters
- arguments.callee cannot be used
- arguments.caller cannot be used
- Prohibit this from pointing to global objects
- You cannot use fn.caller and fn.arguments to get the stack of function calls
- Added reserved words (such as protected, static and interface)
Pay attention to the limitation of this. In ES6 module, the top-level this points to undefined, that is, this should not be used in the top-level code.
2, Use of strict mode
1. Call strict mode
Turn on strict mode for the entire script file
You need to put a specific statement before all statements "use strict";
// The entire script turns on strict mode syntax "use strict"; var v = "Hi! I'm a strict mode script!";
When merging script files, pay special attention to the impact of strict mode and non strict mode
The solution is to include the contents of the entire script in a function, and then use strict mode in this external function. This can eliminate the problem of merging, but this means that you must declare a global variable outside the scope of the function.
Turn on strict mode for a function
hold "use strict"; (or ' use strict'; ) The declaration is placed word for word before all statements in the body of the function.
function strict() { // Function level strict schema syntax 'use strict'; function nested() { return "And so am I!"; } return "Hi! I'm a strict mode function! " + nested(); } function notStrict() { return "I'm not strict."; }
2. Change of strict mode
(1) Turn fault into exception
In strict mode, some previously accepted fault errors will be considered exceptions. JavaScript is designed to make it easier for new developers to start, so sometimes it will give new non error semantics to the original error operation Sometimes this can solve the current problem, but sometimes it will leave a bigger problem for the future. The strict model regards these mistakes as errors so that they can be found and corrected immediately
- Global variables can no longer be created unexpectedly in strict mode
In normal JavaScript, assigning a wrong named variable name will add a property to the global object and continue to "work" (although it may fail in the future: it is possible in modern JavaScript). In strict mode, the unexpected creation of a global variable is replaced by an error thrown:
"use strict"; // Suppose there is a global variable called mistypedVariable mistypedVaraible = 17; // Because the variable name is misspelled // This line of code will throw ReferenceError
- Strict mode causes the assignment operation that causes silent failure to throw an exception
Silent failure means that no error is reported and there is no effect
NaN Is a non writable global variable. In normal mode, give NaN The assignment will not have any effect; the developer will not receive any error feedback. However, in strict mode, the NaN Assignment will throw an exception. Any assignment operation that causes silent failure in normal mode (assigning a value to a non writable attribute, assigning a value to a read-only attribute, and assigning a value to a non extensible object)( non-extensible object) will throw an exception:
"use strict"; // Assign a value to a non writable property var obj1 = {}; Object.defineProperty(obj1, "x", { value: 42, writable: false }); obj1.x = 9; // Throw TypeError error // Assign a value to a read-only property var obj2 = { get x() { return 17; } }; obj2.x = 5; // Throw TypeError error // Assign a value to a new property of a non extensible object var fixed = {}; Object.preventExtensions(fixed); fixed.newProp = "ohai"; // Throw TypeError error
- In strict mode, an exception is thrown when an attempt is made to delete a property that cannot be deleted
"use strict"; delete Object.prototype; // Throw TypeError error
- It is required that all attribute names within an object must be unique within the object (before Gecko version 34)
In normal mode, duplicate name attributes are allowed, and the last duplicate name attribute determines its attribute value. Because only the last attribute works, when the code wants to change the attribute value instead of modifying the last duplicate name attribute, copying this object will produce a series of bug s. In strict mode, duplicate name attributes are considered to be syntax errors:
"use strict"; var o = { p: 1, p: 2 }; // !! Syntax error
- The parameter name of the function is required to be unique
In normal mode, the last duplicate parameter name will mask the previous duplicate parameters. The previous parameters can still be passed arguments[i] is not completely inaccessible. However, this hiding is meaningless and may be unexpected (for example, it may have been typed wrong). Therefore, in the strict mode, duplicate parameters are considered to be syntax errors:
function sum(a, a, c) { // !! Syntax error "use strict"; return a + a + c; // There will be an error when the code runs here }
- Strict mode prohibits octal digit syntax
ECMAScript does not contain octal syntax, but all browsers support this octal syntax starting with zero (0): 0644 === 420 also "\ 045" = = "%". ECMAScript 6 supports prefixing a number with "0o" to represent an octal number
var a = 0o10; // ES6: octal
- supplement
Strict mode prohibition setting in ECMAScript 6 primitive If the strict mode is not adopted, the setting of the property will be simply ignored (no OP). If the strict mode is adopted, the TypeError error
(function() { "use strict"; false.true = ""; //TypeError (14).sailing = "home"; //TypeError "with".you = "far away"; //TypeError })();
(2) Strict mode simplifies the use of variables
Strict mode simplifies the way variable names in code are mapped to variable definitions. Many compiler optimizations rely on the ability to store the X location of variables: This is very important for the overall optimization of JavaScript code. In some cases, JavaScript makes the basic mapping of names to variable definitions in code only occur at runtime. Strict mode removes most of this, Therefore, the compiler can better optimize the code of strict mode
- Strict mode disabled with
The problem caused by with is that any name in the block can be mapped to the attributes of the object passed in by with, or to variables (even global variables) within the scope surrounding the block. All these are determined at run time: they cannot be known before the code runs. In strict mode, use with It will cause syntax errors, so there will be no case that the variables in the with block decide where to reference at runtime:
!function () { with({ x: 1 }) { console.log(x); //1 } }() !function () { 'use strict'; with({ x: 1 }) { console.log(x); //SyntaxError !!! syntax error // If strict mode is not enabled, will the x in with point to the x above with, or obj.x? // If we don't run the code, we can't know. Therefore, this kind of code makes the engine unable to optimize and slow down. } }()
A substitution The simple method of with is to assign the target object to a short named variable, and then access the corresponding properties on the variable
Note:
When the interpreter interprets a statement, if it starts with function, it will be understood as a function declaration.
Adding a "!" in front can make the interpreter understand as a function expression, so it can be called immediately
- Deleting declared variables is prohibited
delete name Syntax errors can occur in strict mode:
"use strict"; var x; delete x; // !!! syntax error eval("var y; delete y;"); // !!! syntax error
- arguments becomes a static copy of the parameter
In non strict mode, the elements and corresponding parameters in the arguments object are references to the same value
!function(a) { arguments[0] = 100; console.log(a); //100 }(1); !function(a) { 'use strict'; arguments[0] = 100; console.log(a); //1 }(1);
However, the parameter passed is an object. arguments and parameters are shared and passed.
!function(a) { 'use strict'; console.log(a.x); //1 arguments[0].x = 100; console.log(a.x); //100 }({x: 1});
- eval Becomes a separate scope
In normal mode, code eval("var x;") A new variable will be introduced to the surrounding function or global x . This means that, in general, Include in a eval All names in the called function that are not referenced to parameters or local variables must be mapped to a specific definition at run time (because eval A new variable that may be introduced overrides its outer variable). In strict mode eval Just create variables for the code being run, so eval Does not map names to external variables or other local variables:
!function() { eval('var evalVal = 2;'); console.log(typeof evalVal); //number }(); !function() { 'use strict'; eval('var evalVal = 2;'); console.log(typeof evalVal); //undefined }();
- eval and arguments become keywords and cannot be used as variables or function names
- No longer supported arguments.callee
In normal mode, arguments.callee Points to the function currently executing. This effect is very small: just name the execution function directly! In addition, arguments.callee It is very unfavorable for optimization, such as inline functions, because arguments.callee Will rely on references to non inline functions. In strict mode, arguments.callee It is an undeletable property, and an exception will be thrown during assignment and reading:
"use strict"; var f = function() { return arguments.callee; }; f(); // Throw type error
- this points to undefined
General function calls (not method calls of objects, and this is not modified with apply/call/bind, etc.), this points to undefined, not global objects
!function () { function fun() { return this; } console.log( fun() ); //Window }(); !function () { 'use strict'; function fun() { return this; } console.log( fun() ); //undefined }();
- When apply/call/bind is used, this point changes
Using apply/call/bind, when the passed in parameter is null/undefined, this points to null/undefined instead of the global object
!function () { function fun() { return this; } console.log( fun.apply(null) ); //Window console.log( fun.apply(undefined) ); //Window console.log( fun.call(null) ); //Window console.log( fun.call(undefined) ); //Window console.log( fun.bind(null)() ); //Window console.log( fun.bind(undefined)() ); //Window }(); !function () { 'use strict'; function fun() { return this; } console.log( fun.apply(null) ); //null console.log( fun.apply(undefined) ); //undefined console.log( fun.call(null) ); //null console.log( fun.call(undefined) ); //undefined console.log( fun.bind(null)() ); //null console.log( fun.bind(undefined)() ); //undefined }();
- fun.caller and fun.arguments are undeletable attributes, and errors will be reported when saving values and taking values:
When a function called fun is being called, fun.caller is the last function to call fun, and fun.arguments contains the formal parameters used to call fun. Both extension interfaces are problematic for "secure" JavaScript because they allow "secure" code to access "proprietary" functions and their (usually unprotected) formal parameters
function restricted() { "use strict"; restricted.caller; // Throw type error restricted.arguments; // Throw type error } function privilegedInvoker() { return restricted(); } privilegedInvoker();
- arguments.caller is a property that cannot be deleted, and an error will be reported when saving and taking values:
In some old ECMAScript implementations, arguments. Caller used to be an object in which the stored attributes point to the variables of that function. This is a security risk because it breaks the hidden reserved values through function abstraction; It is also the reason for a lot of optimization work. For these reasons, current browsers do not implement it. However, because of its historical function, arguments.caller is also an attribute that cannot be deleted in strict mode. An error will be reported when assigning or taking values:
!function () { 'use strict'; var fun = function () { return arguments.callee; }; fun(); //TypeError }();
- Some keywords are reserved
implements, interface, let, package, private, protected, public, static and yield
In strict mode, you can no longer use these names as variable names or parameter names.
function package(protected) { // !!! "use strict"; var implements; // !!! interface: // !!! while (true) { break interface; // !!! } function private() { } // !!! } function fun(static) { 'use strict'; } // !!!
- Function declarations that are not at the script or function level are prohibited
!function () { "use strict"; if (true) { function fun() {} console.log( fun() ); //IE10 reports an error. No error is reported for IE11, IE7~9, Chrome and FF. } for (var i = 0; i < 5; i++) { function fun2() {} console.log( fun2() ); //IE10 reports an error. No error is reported for IE11, IE7~9, Chrome and FF. } function fun3() { // legitimate function fun4() {} //Equally legal } }();