iT邦幫忙

2021 iThome 鐵人賽

DAY 4
0
Modern Web

舌尖上的JS系列 第 4

D4 - 加鹽不加價 嚴格模式開啟

  • 分享至 

  • xImage
  •  

前言

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

上一篇
D3 - 今天點個 String Methods 套餐
下一篇
D5 - 你不知道 Combo : 前菜 Hoisting
系列文
舌尖上的JS30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
Chris
iT邦新手 3 級 ‧ 2021-09-19 17:19:28

那個邊走邊吃的同學,學號幾號?

Hooo iT邦新手 4 級 ‧ 2021-09-19 18:58:17 檢舉

立馬遮住學號跑給教官追

我要留言

立即登入留言