javascript严格模式

1.什么是严格模式?

js运行有两种模式:一种是普通模式;一种是严格模式。

严格模式是ES5添加的,是比普通模式多一部分的js规则。如果在ES5之前js解析引擎,会忽略严格模式。

js一般默认是普通模式,ES6的模块和Class类默认是严格模式。

2. 严格模式的使用场景

严格模式的触发是使用: "use strict"

有两种使用场合:一种是脚本范围;一种是函数范围

1.脚本范围

1.在html文件中,可以在<script> 标签内的顶部直接使用"use strict";

"use strict"上面不能有可执行代码,否则失效;但是上面可以是注释内容或者空行。

❗️一个脚本内抛出异常,后面的代码不再执行;但是其他的脚本可以。如下:

<script>
  console.log(1); 
  "use strict"; //上面有代码,自动失效
  a=6;
</script>
<script>

  /* 这是个脚本注释,并且上面空了一行*/
  "use strict"; // 严格模式;下面是声明时报错
  b=6; // Uncaught ReferenceError: b is not defined
</script>
<script>
  "use strict"; // 严格模式
  c=6; // Uncaught ReferenceError: c is not defined
</script>

2.在一个脚本文件中,在顶部声明"use strict";顶部有注释或者空行(空;行不可以)也可以。

//--- es5.js
//
顶部的注释;并且有一个空行,整个文件都是严格模式 "use strict"; function test(a,a) { // Uncaught SyntaxError: Duplicate parameter name not allowed in this context // 严格模式不允许参数重复;声明时报错 }

 上面的写法有隐患,如果项目内部需要脚本合并,如严格模式A.js和普通模式B.js,如果A在前,那么

B也会被解释成严格模式;如果B在前,那么A的严格模式会失效。

所以,如果是单独的文件,可以使用立即执行函数包裹以下,这样可以避免脚本合并的BUG。

// 这个是A.js的代码;代码效果和上面的相同,但是可以保证代码的独立
(function() {
   "use strict"; // 函数内部严格模式
    function test(a,a) { // Uncaught SyntaxError: Duplicate parameter name not allowed in this context
    }
})();

2.函数范围

在一个函数内顶部使用"use strict";那么在一个函数内是严格模式。

    function test() {
      // 函数的注释
      "use strict";
      t = 7;
    }
    // 声明时不报错;执行时报错
    test();  // Uncaught ReferenceError: t is not defined

3. 浏览器控制台范围

开发者最方便的调试工具是console控制台;默认是普通模式,可以手动设置严格模式;

 

 

 3. 严格模式的内容

1. 显式报错

将普通模式中默默失败的错误,改为显式报错。

  • 1. 只读属性赋值报错;删除不可配置属性报错

原先只读属性赋值或者删除不可配置属性,默默失败,不会抛出异常;严格模式下,会抛出异常。

"use strict";
class A {
}
class B{}
// 类的prototype属性的writable,configurable,enumerable都是false
A.prototype = new B(); // Uncaught TypeError: Cannot assign to read only property 'prototype' of function 'class A {}'
delete A.prototype; // Uncaught TypeError: Cannot delete property 'prototype' of class A {}'
  • 2.只设置了取值器的对象不可写
"use strict";
var a = {
    get prop() {
        return 1;
    }
}
a.prop = 5; //Uncaught TypeError: Cannot set property prop of #<Object> which has only a getter
  • 3.禁止扩展的对象不可扩展(不能添加新属性)
"use strict";
var a = {};
Object.preventExtensions(a);
a.x = 0; //Uncaught TypeError: Cannot add property x, object is not extensible
  • 4.eval,arguments不可用作标识名

javascript中的保留字在严格模式下都会报错;实际开发中注意变量名不要是保留关键字。

非严格模式下,不会报错。

"use strict";
var eval = 5; //Uncaught SyntaxError: Unexpected eval or arguments in strict mode
function test(arguments) { //Uncaught SyntaxError: Unexpected eval or arguments in strict mode
}
  • 5.函数参数名不能重复
  • 6. 禁止使用0前缀表示八进制数。

ES6中也有规定,八进制数应该使用“0o”表示。

"use strict";
var a = 0o10;
console.log(a); // 8
var b = 010; // Uncaught SyntaxError: Octal literals are not allowed in strict mode.

2. 加强安全

从语法书写上避免错误的产生。

  • 1. 严格模式下,不允许this指向window

js引擎将其指向undefined。这个很好的解释了React类组件中方法必须绑定this,

否则默认this是undefined。

这时fn.call()/fn.call(null)/fn.call(undefined)不再默认绑定window。绑定的就是括号中的内容。

  • 2. 不允许未声明的变量出现

即变量必须使用var, let等声明,否则报错。原来未声明的变量会默认成为全局变量。

"use strict";
a = 5;  // Uncaught ReferenceError
  • 3.禁止使用fn.caller/fn.arguments

首先fn.caller不是标准语法;生产环境禁止使用;fn.arguments已被废弃

但是某些情况下也会使用。

fn.caller是返回fn的调用栈,即触发该函数的函数;

如果在全局环境下调用,fn.caller()是null。

// 这是非严格模式;只是为了解释caller的概念;严格模式下报错
function test() {
    a();
    console.log(test.caller);//null
}
function a() {
    console.log(a.caller); // function test(){a();}
}
test();

fn.arguments其实就是参数对象。可以在函数中直接使用arguments对象。

  • 4.禁止使用arguments.callee/arguments.caller

这两个属性已经废弃。普通模式下使用,代码无效,不报错;严格模式下报错。

原来arguments.callee表示当前函数;arguments.caller和fn.caller一样。

  • 5.不可删除声明的普通变量

普通模式下可以删除,并且可以删除成功。

"use strict";
let a = 6;
delete a; //Uncaught SyntaxError: Delete of an unqualified identifier in strict mode.
  • 6.严格模式下原始类型的值不能赋属性

普通模式下不报错,会自动将原值值转为包装对象。

"use strict";
(1).prop = 9; // Uncaught TypeError: Cannot create property 'prop' on number '1'

3. 禁止出现动态作用域

普通模式下,eval()和with()会在执行时动态生成作用域。

  • 1. 禁止使用with语句

在严格模式下,使用with语句会报错。其实普通模式下,也不要使用with语句。

"use strict";
var obj ={};
with(obj) { //Uncaught SyntaxError: Strict mode code may not include a with statement
    a = 5;
}
  • 2.创建eval作用域

严格模式下,eval()会创建一个eval函数内部的作用域。

普通模式下, eval内部代码所在的作用域是函数所在的作用域。

// 普通模式下
function test() {
    var x = 5;
    eval("var x = 6"); //相当于直接var x= 6;
    console.log(x); // 6
}
test();
//  严格模式下
"use strict"; // 1.第一种声明位置
function test() {
    // "use strict"; // 2.也可以在这里声明
    var x = 5;
    eval("var x = 6"); // 只在eval内部有效
    // 3. 还可以如下声明
    // eval('"use strict"; var x= 6');
    console.log(x); // 5
}
test();
  • 3.arguments对象不再随参数改变而改变
// 普通模式
function test(a) {
   a = 2;
   return [a, arguments[0]];
}
console.log(test(1));  // [2, 2]
// 严格模式
"use strict";
function test(a) {
   a = 2;
   return [a, arguments[0]]; 
}
console.log(test(1)); // [2, 1]

4.向未来版本过渡

 

posted @ 2019-10-20 21:26  Lyra李  阅读(1191)  评论(0编辑  收藏  举报