23严格模式

概述

严格模式是什么

严格模式是Javascript中的一种限制性更强的変种方式。严格模式不是一个子集:它在语义上与正常代码有着明显的差异。

不支持严格模式的刘览器与支持严格模式的浏览器行为上也不一样,所以不要在未经严格模式特性测试情况下使用严格模式。

严格模式可以与非严格模式共存,所以脚本可以逐渐的选择性加入严格模式。

严格模式的目的

首先,严格模式会将Javascript陷阱直接变成明显的错误。

其次,严格模式修正了一些引擎难以优化的错误:同样的代码有些时候严格模式会比非严格模式下更快

第三,严格模式禁用了一些有可能在未来版本中定义的语法。

开启严格模式

全局开启严格模式

只需要在全局写以下字符串即可。作用于全局作用域

"use strict";
a = 100;
console.log(a);

函数开启严格模式

在函数内写以下字符串即可。只作用于函数作用域。例如:

function fn() {
  "use strict";
  v = 200;
  console.log(v);
}

变量

禁止意外创建变量

  1. 非严格模式 在函数作用域中定义变量,不适用var关键字那么自动将其提升为全局变量。例如: function fn() { w = 200; console.log(w); //200 } fn(); console.log(w); //200
  2. 严格模式下 在严格模式下则会抛出异常 "use strict"; function fn() { // 在函数作用域中定义变量 - 不适用var关键字-> 自动将其提升为全局变量 w = 200; console.log(w); } fn(); console.log(w); // v = 100; // ^

静默失败转为异常

所谓静默失败就是既不报错也没有任何效果,例如改变常量的值。在严格模式下,静默失败会转换成抛出异常。

例如:

// 定义一个常量
const v = 3.14;

// 重新赋值
v = 1.14;
console.log(v);

以上代码在稍微老一点的浏览器可能并不会报错(新版报错),但开启严格模式后,一定会报错。

禁止delete关键字

在严格模式下不能对变量使用delete运算符。

例如:

var v = 100;

console.log(v); //100

delete v;
console.log(v); //100
  1. 严格模式下会抛出一个错误
  2. 非严格模式下会输出两个100

严格模式下禁用delete只针对删除变量,而不是数组元素和对象属性。

"use strict";
var arr = [0, 1, 2, 3, 4];
delete arr[0];
console.log(arr); //[ <1 empty item>, 1, 2, 3, 4 ]

var obj = {
  name: "张无忌",
};
delete obj.name;
console.log(obj.name); // undefined

对变量名的限制

在严格模式下,JavaScript对变量名也有限制。特别不能使用如下内容作为变量名:

  • implements
  • interface
  • let
  • package
  • private
  • protected
  • public
  • static
  • yield

上述关键词表示在ECMAScript的下一个版本中可能会用到他们,在严格模式下使用以上字符作为变量名会导致语法错误。

对象

不可删除的属性

"use strict";
delete Object.prototype;
console.log(Object.prototype);
// 报错

非严格模式下不会报错,但也不会删除成功。但在严格模式下会直接抛出错误。

但严格模式并不会限制所有对象,例如:

"use strict";
delete Math.random;
console.log(Math.random); //undefined
Math.random();

即使在严格模式下,还是可以删除Math.random方法。

属性名必须唯一

在严格模式下,一个对象内的所有属性名在对象内必须唯一。

"use strict";
var obj = {
  name: "张无忌",
  name: "周芷若",
};
console.log(obj.name); // 周芷若

开启严格模式后,如果对象具有相同属性,那么并不会报错,而是覆盖。

只读属性的赋值

"use strict";
var obj = {};
Object.defineProperty(obj, "age", {
  value: 18,
});
// 针对只读属性进行修改操作

obj.age = 80;
console.log(obj.age);

delete obj.age;
console.log(obj.age);

对于不可修改的属性,无论是修改还是删除都会发生报错。

不可扩展的对象

在严格模式下,不能为不可扩展的对象添加新属性。

"use strict";
var obj = {};
// 设置对象obj是一个不可扩展的对象
Object.preventExtensions(obj);

// 为对象obj新增属性或方法

obj.name = "张无忌";
console.log(obj);

以上代码在严格模式下会报错,非严格模式下不会报错。

函数

参数名必须唯一

在严格模式下,要求命名函数的参数必须唯一。

function fn(a, a, b) {
  console.log(a + a + b);
}
fn(1, 2, 3); //7

例如以上代码,非严格模式下会输出7,两个参数a都会被当作2;但在严格模式下,会抛出错误。

arguments的不同

在严格模式下, arguments对象的行为也有所不同。

  • 非严格模式下,修改命名参数的值也会反应到arguments对象中。
  • 严格模式下,命名参数与arguments对象是完全独立的。
"use strict";
function fn(value) {
  var value = "张无忌";
  console.log(value); // 张无忌
  console.log(arguments[0]); //严格模式下为周芷若 非严格模式下为周芷若
}
fn("周芷若");

非严格模式下arguments对象获取参数的值与形参有关。(如果局部变量与形参名相同,则根据就近原则获取);严格模式下arguments对象获取参数的值与形参无关。

arguments.callee()

在严格模式下,不能使用armaments对象的callee()方法。

"use strict";
function fn() {
  return arguments.callee;
}
fn();

以上代码在严格模式下会直接报错。

函数声明的限制

在严格模式下,只能在全局域和函数域中声明函数。

"use strict";
// 在全局作用域
function fn() {
  function n() {}
}

for (var i = 0; i < 10; i++) {
  // ECMAscript 6 新增 - 存在块级作用域
  var v = 100;
  // 开启严格模式后在块级不能定义函数
  function f() {
    console.log("this is function");
  }
}
console.log(v); // 100
f(); // ReferenceError: f is not defined

在严格模式下,函数的定义只能在全局作用域与函数作用域,不能在块级作用域

增加eval()作用域

在严格模式下,使用eval()函数创建的变量只能在eval()函数内部使用。

eval("var v = 100");
console.log(v);

以上代码在非严格模式下会输出100,而在严格模式下会抛出错误。

在严格模式下,会增加eval作用域。也就是说在eval函数定义的变量只能在当前eval函数使用。

arguments对象–禁止读写

在严格模式下,禁止使用eval()和arguments作为标示符,也不允许读写它们的值。

  • 使用var声明。
  • 赋予另一个值
  • 尝试修改包含的值。
  • 用作函数名。
  • 用作命名的函数的参数。
  • 在 try-catch语句中用作例外名。

以下语句在严格模式下均会报错:

eval = 17;

arguments++;

++eval;

var obj = {
  set p(arguments) {},
};

var eval;

try {
} catch (arguments) {}

function x(eval) {}

function (eval) { }

function arguments() { }

var y = function eval() { }

var f = new Function('arguments', "'use strict';return 17;")

抑制this

  • 在非严格模式下使用数的apyly()call()方法时,nullundefined值会被转换为全局对象。
  • 在严格模式下,函数的this值始终是指定的值(无论什么值)。
"use strict";
var v = 100;

function fn() {
  console.log(this.v);
}

var obj = {
  v: 200,
};
fn.call(null);

在严格模式下会抛出错误,必须明确指定this,例如fn.call(obj);

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 02JavaScript基础语法部分

    判断包装类型不能使用typeof而是使用instanceof 。语法结构变量名/对象名 instanceof 构造函数/数据类型

    Dreamy.TZK
  • 04JavaScript数组

    所以可以得到对于索引数组,长度是有效的;但对于关联数组无法获取长度。而对于稀疏数组,取决于键。

    Dreamy.TZK
  • 18Function类型

    函数是这样的一段 Javascript代码,它只定义一次,但可能被执行或调用多次。

    Dreamy.TZK
  • Django上线部署之Apache的方法

      1.Windows Server 2016 Datacenter 64位   2.SQL Server 2016 Enterprise 64位   3....

    砸漏
  • Arthas 手动触发生产定时任务的危险操作

    最近来了个实习僧小弟,安排他实现对目标网站 连通性检测的小功能,简单讲就是将下边的shell 脚本换成Java 代码来实现

    冷冷
  • 【开源】我的分页控件正式命名为QuickPager ASP.NET2.0分页控件

    分页控件正式命名为 QuickPager ASP.NET2.0分页控件 。 版本号:2.0.0.1 Framework:.net2.0 分页方式:PostB...

    用户1174620
  • kubernetes 应用管理之道 - 有状态服务

    用户通过 Deployment、ReplicationController 可以方便地在 kubernetes 中部署一套高可用、可扩展的分布式无状态服务。这类...

    kubernetes中文社区
  • TortoiseGIT提交

    TortoiseGit,Git客户端,32/64位最新版及对应的语言包下载地址:https://tortoisegit.org/download/

    达达前端
  • SpringMVC系列知识:(二)什么是springMVC,为什么要使用springMVC

    现在使用springMVC,就是一个框架,就是将Servlet进行了封装,提供一个公共的Servlet。该Servlet可以根据请求动态的调用对应的逻辑方法完成...

    一天不写程序难受
  • .Net 转战 Android 4.4 日常笔记(1)--工具及环境搭建

    闲来没事做,还是想再学习一门新的技术,无论何时Android开发比Web的开发工资应该高40%,我也建议大家面对移动开发,我比较喜欢学习最新版本的,我有java...

    用户1149182

扫码关注云+社区

领取腾讯云代金券