浅析javascript严格模式和正常模式的区别

什么是严格模式

除了正常的运行模式,JavaScript 还有第二种运行模式:严格模式(strict mode)。顾名思义,这种模式采用更加严格的 JavaScript 语法。
同样的代码,在正常模式和严格模式中,可能会有不一样的运行结果。一些在正常模式下可以运行的语句,在严格模式下将不能运行。
严格模式:规避了js里不严谨不规范的地方,增强了代码的安全性,提高了编译器的编译效率,为后续版本做铺垫。

设计目的

早期的 JavaScript 语言有很多设计不合理的地方,但是为了兼容以前的代码,又不能改变老的语法,只能不断添加新的语法,引导程序员使用新语法。
严格模式是从 ES5 进入标准的,主要目的有以下几个。
一 . 明确禁止一些不合理、不严谨的语法,减少 JavaScript 语言的一些怪异行为。
二 . 增加更多报错的场合,消除代码运行的一些不安全之处,保证代码运行的安全。
三 . 提高编译器效率,增加运行速度。
四 . 为未来新版本的 JavaScript 语法做好铺垫。
总之,严格模式体现了 JavaScript 更合理、更安全、更严谨的发展方向

启用方法

进入严格模式的标志,是一行字符串use strict。
‘use strict’; strict 严格的
老版本的引擎会把它当作一行普通字符串,加以忽略。新版本的引擎就会进入严格模式。
严格模式可以用于整个脚本,也可以只用于单个函数
整个脚本文件:
use strict放在脚本文件的第一行,整个脚本都将以严格模式运行。如果这行语句不在第一行就无效,整个脚本会以正常模式运行。
(严格地说,只要前面不是产生实际运行结果的语句,use strict可以不在第一行,比如直接跟在一个空的分号后面,或者跟在注释后面。)

<script>
  'use strict';
   console.log('这是严格模式');
</script>
<script>
   console.log('这是正常模式');
</script>

上面代码中,一个网页文件依次有两段 JavaScript 代码。前一个

<script>
  console.log('这是正常模式');
  'use strict';
</script>

单个函数:
use strict放在函数体的第一行,则整个函数以严格模式运行。

function strict() {
  'use strict';
  return '这是严格模式';
}
function notStrict() {
  return '这是正常模式';
}

变量声明(必须要使用var)
函数不能有重名的参数
正常模式下,如果函数有多个重名的参数,可以用arguments[i]读取。严格模式下,这属于语法错误。

function f(a, a, b) {
  'use strict';
  return a + b;
}

禁止八进制的前缀0表示法
正常模式下,整数的第一位如果是0,表示这是八进制数,比如0100等于十进制的64。严格模式禁止这种表示法,整数第一位为0,将报错。

'use strict';
var n = 0100;

禁止 this 关键字指向全局对象
正常模式下,函数内部的this可能会指向全局对象(window),严格模式禁止这种用法,避免无意间创造全局变量。

function f() {// 正常模式
  console.log(this === window);
}
f() // true
function f() {// 严格模式
  'use strict';
  console.log(this === undefined);
}
f() // true

上面代码中,严格模式的函数体内部this是undefined。这种限制对于构造函数尤其有用。使用构造函数时,有时忘了加new,这时this不再指向全局对象,而是报错。

function f() {
  'use strict';
  this.a = 1;
};f();// 报错,this 未定义

严格模式下,使用with语句将报错。

'use strict';
var obj = {v:1};
with (obj) {  // SyntaxError: Strict mode code may not include a with statement
  v = 2;//obj.v = 2;
}

相当于
obj.v
创设 eval 作用域
正常模式下,JavaScript 语言有两种变量作用域(scope):全局作用域和函数作用域。严格模式创设了第三种作用域:eval作用域。
正常模式下,eval语句的作用域,取决于它处于全局作用域,还是函数作用域。严格模式下,eval语句本身就是一个作用域,不再能够在其所运行的作用域创设新的变量了,也就是说,eval所生成的变量只能用于eval内部。

(function () {
  'use strict';
  var x = 2;
  console.log(eval('var x = 5; x')) // 5
  console.log(x) // 2
})()

上面代码中,由于eval语句内部是一个独立作用域,所以内部的变量x不会泄露到外部
删除变量
通过关键字delete删除
delete关键字通常同来删除对象的属性值和属性名
也可以用来删除普通模式下未声明的变量 有var let const声明的变量在普通模式下无法删除
用delete删除显示申明的标识符、名称和具名函数。
严格模式下
只有configurable设置为true的对象属性,才能被删除。

   "use strict";
  var x;
  delete x; // 语法错误
  var obj = Object.create(null, {'x': {
      value: 1,
      configurable: true
  }});
  delete oobj.x; // 删除成功

arguments
arguments在严格模式下有着很有意思的一面
普通模式下

function f(x){
  console.log(arguments[0]);
  x=20;
  console.log(arguments[0])
}
f(10) // 10  20 

严格模式下
有名参数是arguments参数的静态副本,而非引用。

<script>
    'use strict';
    function fun() {
        console.log(arguments[0]);
        arguments[0] = 20
        console.log(arguments[0]);
    }
    fun(10) // 10 20
    
    function f(x) {
        console.log(arguments[0]);
        arguments[0] = 20;
        console.log(x);
        x = 30
        console.log(arguments[0])
        console.log(x);
    }
    f(10) // 10  20 30
</script>

在无论有名或无名参数的情况下我们修改arguments[0]都可以修改
而在有名参数的情况下我们修改arguments[0]发现和命名参数没有任何的冲突
命名参数就是我们修改的命名参数的值
arguments[0]则是我们修改的另一个值

函数形参声明名不能重复
普通模式下
形参声明相同会导致函数内部打印参数选择第二个形参的值

<script>
    function fun(a, a) {
        console.log(a);
    }
    fun(10, 20) // 20
</script>

严格模式直接报错

<script>
    'use strict';
    function fun(a, a) {
        console.log(a);
    }
    fun(10, 20) // Uncaught SyntaxError: Duplicate parameter name not allowed in this context
</script>
发布了4 篇原创文章 · 获赞 1 · 访问量 126

猜你喜欢

转载自blog.csdn.net/lemon_hongcha/article/details/104625224
今日推荐