D4 - 加盐不加价 严格模式开启

前言

JavaScript 相较是个自由的语言,在学习语法时会发现,咦 明明规则是这样,怎麽那样也可以?

在 2009 年的 ECMAScript 5 中新增了严格模式,就像加入了一位风纪股长,以前睁一只眼闭一只眼容许的灰色地带语法,现在会毫不留情的被指出!
(你 那个黄头发的! 衣服扎进去)

此篇文将会分享:

  • 什麽是严格模式
  • 严格模式怎麽使用
  • 严格模式的作用范围
  • 严格模式下哪些行为被禁止
  • 严格模式的支援程度

ECMA 规范的严格模式

在严格模式下,以往一些容易造成混淆或是默认的不良语法,现在会直接跳出 error 讯息,修正了一些会阻碍引擎最佳化的问题,也为了之後可能的变动铺路,像是新增了一些保留字。
严格模式提高了整体 code 的稳定与安全程度。

以下截图是 ECMA 针对 strict mode 的规范

要怎麽套用严格模式呢?
作法很简单,只要加上 'use strict' 这段语法。
可以放在 全域 或是 区域函数 内,但请务必放在最开头,依照规范说明,这样底下的 code 才能有效的被视为 strict mode code

特别的是加在区域函数内的 'use strict' 并不会影响到全域,而是只在该 function 的范围内实施严格模式!

但,就算没有特别加上 'use strict',在某些情况也可能默默进入严格模式,依照规范的第 2 和 3 点,在 module 模组 下 以及 使用 classDeclaration, classExpression, 这时候都会视为 strict mode code!

好的,那了解了严格模式的使用和作用范围後,接下来 就来看看到底哪些行为是在严格模式下不被允许的吧~

严格模式禁止行为

1. 未经宣告的变数进行赋值

在一般模式下,JS 接受赋予值到一个未经宣告过的变数,但这件事在严格模式下被禁止了,会直接抛出变数未定义的错误讯息

//一般模式
cookie = 'oreo'; // 无var,let,const宣告
console.log(cookie) // 'oreo'

//严格模式
'use strict'
cookie = 'oreo' // Uncaught ReferenceError: cookie is not defined

2. 使用 delete 删除变数或函数

在一般模式下使用 delete 删除变数和函数只会跑出 false,不会有实质上的效果但也不会报错,但在严格模式下会侦测此错误,并抛出错误讯息

//一般模式
let cookie = 'oreo';
delete cookie; // false
console.log(cookie) // 还是可以印出 'oreo'

//严格模式
'use strict'
let cookie = 'oreo';
let function x (a,b) {};

delete cookie; // SyntaxError: Delete of an unqualified identifier in strict mode
delete x; // SyntaxError: Delete of an unqualified identifier in strict mode

3. 重复的参数名称

一般模式下若 function 放入了两个相同的参数名称,後位的参数值会取代前面的参数,但在严格模式下禁止了重复的参数命名

//一般模式
function plus(x,x,y) {
  return (x+y);
}

plus(1,2,4)  // 取第二个x值, 得到6

//严格模式
'use strict'
function plus(x,x,y) {
  return (x+y);
}

plus(1,2,4)  // SyntaxError: Duplicate parameter name not allowed in this context

4. 八进制的数字实字 Octal numeric literals 及 逃脱字元

不接受使用八进制的数字实字及逃脱字元

//一般模式
let octalNumeric = 010;
let escape = '\010';

//严格模式
'use strict'
let octalNumeric = 010; // SyntaxError: Octal literals are not allowed in strict mode.
let escape = '\010'; // SyntaxError: Octal escape sequences are not allowed in strict mode.

5. 对只可读取 read-only 或 使用 getter 读取的属性 进行写入

某些属性规定只能 read-only 或 get-only,若强行对他们做写入修改,一般模式下并不会产生作用但也不会报错,但这件事在严格模式下将会明确的被当错误丢出!

对 read-only property 写入新的值

//一般模式
const obj = {};
Object.defineProperty(obj, "x", {value:0, writable:false}); // 不允许写入

obj.x = 3.14;
console.log(obj.x) // 0, 不会报错但新赋予的值也不会被写入 

//严格模式
"use strict";
const obj = {};
Object.defineProperty(obj, "x", {value:0, writable:false});

obj.x = 3.14;  // TypeError: Cannot assign to read only property 'x' of object '#<Object>'

对 getter 读取的 property 写入新的值

// 一般模式
const obj = {
  get x() {
    return 0;
  },
};

obj.x = 3.14;
console.log(obj.x); // 0, 不会报错但新赋予的值也不会被写入 

//严格模式
'use strict'
const obj = {
  get x() {
    return 0;
  },
};

obj.x = 3.14; // TypeError: Cannot set property x of #<Object> which has only a getter

6. 将 eval 和 argument 当作变数名称

//一般模式
let eval = 1;
let argument = 2;

//严格模式
'use strict'
let eval = 1;
let argument = 2;

SyntaxError: Unexpected eval or arguments in strict mode

7. with

目前还没使用过 with 语法,依 MDN with语法 的说明 : with 在一般模式下也不建议使用,有容易造成混淆的问题,但也仅仅是不建议而已,还是可以使用
而在严格模式下是完全禁止 with 语法

//一般模式
let a, x, y;
const r = 10;

with (Math) {
  a = PI * r * r;
  x = r * cos(PI);
  y = r * sin(PI / 2);
}

console.log(a) // 314.1592653589793
console.log(x) // -10
console.log(y) // 10

//严格模式
"use strict";
let a, x, y;
const r = 10;

with (Math) {
  a = PI * r * r;
  x = r * cos(PI);
  y = r * sin(PI / 2);
} 

// SyntaxError: Strict mode code may not include a with statement

8. this 指向不同

在使用一般的函式呼叫时,this 这时会指向全域也就是 global 或 window,但在严格模式下会显示为 undefined

// 一般模式
function myFunction() {
  alert(this);
}
myFunction(); // alert视窗跳出 [object Window] 

// 严格模式
"use strict";
function myFunction() {
  alert(this); 
}
myFunction(); // alert视窗跳出 undefined

9. 新增保留字

另外也预留了一些之後 JavaScript 语法上会用到的保留字,在严格模式下不能使用,否则跳出 SyntaxError: Unexpected strict mode reserved word

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

can I use 严格模式

以下是严格模式在各大浏览器的支援程度,除了 IE9 以外都支援此语法,而其实 'use strict' 在不支援的环境下也仅是为普通字串,顶多无作用但不会跳出错误讯息

Reference:

  • W3School
  • MDN
  • ECMA

<<:  Kotlin Android 第14天,从 0 到 ML - Fragments 和 Fragments 生命周期

>>:  【心得】你今天种菜了吗? grid之路-grid的使用(2)

数据来源身份真实-CBC-MAC

-密码学 问题是关於确保数据本身的完整性和数据来源的真实性,或者所谓的“真实性”,包括这两个概念。...

来做一个色码转换器吧!

前言 今天来做一个色码转换器~ 我们先认识色码之间的关系,拆解步骤後再一步步完成吧! 颜色表示的方法...

创建App-现界面与连接

创建App-现界面与连接 经过了十五天的努力,现在就来看看现有的界面功能吧,我依照功能来区分:登入、...

Day25:今天来聊一下Azure Sentinel中的威胁情报

Azure Sentinel提供资料表来储存可供Kusto查询语言(KQL)查询存取的指标资料。 来...

2.4.13 Design System - Loading Indicator

时常为自己排序 这是一个老生常谈的问题了,工作、家庭、财富、人际、健康,什麽对我们来说是最重要的?...