JS基础:严格模式与非严格模式的区别

803 阅读5分钟

严格模式的概念是从ECMAScript5引入的,通过严格模式,可以在函数内部选择进行较为严格的全局或局部的错误条件检测。 首先我们来看下 MDN中严格模式的描述

  1. 严格模式通过抛出错误来消除了一些原有静默错误。
  2. 严格模式修复了一些导致 JavaScript引擎难以执行优化的缺陷:有时候,相同的代码,严格模式可以比非严格模式下运行得更快。
  3. 严格模式禁用了在ECMAScript的未来版本中可能会定义的一些语法。

如何使用严格模式

  1. 一般情况下我们建议在脚本的最顶部放置 "use strict"
    • 支持严格模式的引擎会启动这种模式,
    • 而不支持该模式的引擎就当遇到了一个未赋值的字符串字面量,会忽略这个编译指示。
  2. 当然也可以在函数中使用严格模式,如下面的示例代码所示:
function striceExample(){ 
  "use strict";
  // 其他逻辑......
}
  1. 现代ES6的代码,支持 classesmodules 高级语言结构,它们会自动启用 use strict。因此,如果我们使用它们,则无需添加 "use strict" 指令。

严格模式与非严格模式的区别

严格模式下变量必须声明才能使用

正常模式中,如果一个变量没有声明就赋值,默认是全局变量。严格模式禁止这种写法,在严格模式下,如果给一个没有声明的变量赋值,那代码在执行时就会抛出ReferenceError

严格模式下禁止使用with语句

因为with语句无法在编译时就确定,属性到底归属于哪个对象,严格模式有利于编译效率提高

with(location){ 
  console.log(href);
}
// 严格模式:抛出语法错误

严格模式下创建eval作用域

正常模式下,js有两种变量作用域,全局作用域和局部作用域,正常模式下eval语句作用域取决于它处于全局作用域还是函数作用域,严格模式下eval语句本身就是作用域,不能够生成全局变量,所生成的变量只能用于eval内部。

例如如下代码:

function testEval(){ 
  eval("var a='lxm'"); 
  alert(a);
}
// 非严格模式:调用 alert(a)时会弹出对话框显示 lxm
// 严格模式:调用 alert(a)时会抛出 ReferenceError

可以在 eval()中声明变量和函数,但这些变量或函数只能在被求值的特殊作用域中有效,随后就将被销毁。

严格模式下禁止this关键字指向全局对象

严格模式下全局作用域中定义的函数中的this为undefined, 以如下代码为例

var name = "lxm";
function showName(){ 
  alert(this.name);
}

showName.call(null);
// 非严格模式:访问全局属性
// 严格模式:抛出错误,因为 this 的值为 null 

上面的代码,如果在是非严格模式下this志向的是全局对象。结果就是弹出对话框显示"lxm"。

而在严格模式下,这个函数的 this 的值是 null,因此在访问 null 的属性时就会抛出错误。

严格模式下禁止在函数内部遍历调用栈

caller:是调用当前函数的函数的引用,即外层函数的引用

function testCaller(){
    "use strict";
    testCaller.caller; //报错
    testCaller.arguments; //报错
}
testCaller();

严格模式下无法删除变量

只有conifgurable设置为true的对象属性才能被删除

"use strict"

var x ;

delete x; //严格模式下报语法错误

var o = Object.create(null,{'x':{

    value: 1,

    configurable: true

}})

delete o.x; //删除成功

严格模式下 显示报错

正常模式下对一个对象的只读属性进行赋值,不会报错,只会默默失败。严格模式下将报错

"use strict";

var obj = {};

Object.defineProperty(obj,"name",{value: 'lxm',writable: false});

obj.name = 2; //报错,因为obj.name属性是不能被修改的,严格模式会报错,正常模式会失败但不报错

严格模式下,不允许对禁止扩展的对象添加新属性

"use strict";

var obj = {};

Object.preventExtensions(obj);//禁止o对象有拓展属性

obj.name = 1; //报错

严格模式下,禁止删除一个不可删除的属性

"use strict";
delete Object.prototype; //报错

严格模式下禁止重复变量声明

let a = 1;
let a = 2; // 严格模式下报错

函数体中的arguments

非严格模式下,修改命名参数的值也会反映到 arguments 对象中,例如:

//修改命名参数的值
//非严格模式:修改会反映到 arguments 中
function showName(name){ 
  name = "lxm";
  alert(name); //"lxm" 
  alert(arguments[0]); //非严格模式:"lxm"
}
showName("lili");

格模式下这两个值是完全独立的。

//修改命名参数的值
//严格模式:修改不会反映到 arguments 中
function showName(name){ 
"use strict"
  name = "lxm";
  alert(name); //"lxm" 
  alert(arguments[0]); //非严格模式:"hi"
}
showName("lili");

严格模式下函数不能有重名的参数

重名的参数在严格模式会报错,正常模式可以通过arguments[i]来获取对应的参数

严格模式下禁止八进制写法

正常情况下整数第一位为0代表八进制,严格模式下整数第一位为0则报错

需要注意:使用parseInt解析八进制字面量在严格模式下会被当作以 0 开头的十进制字面量。

var num = parseInt("010");
//非严格模式:值为 8
//严格模式:值为 10

以上就是对严格模式和正常模式的区别的简单介绍,希望对你有帮助,喜欢的记得点赞哈。