📓
Something About JavaScript
  • Introduction
  • Day 1:前言
  • Day 2:資料型態的夢魘——動態型別加弱型別(1)
  • Day 3:資料型態的夢魘——動態型別加弱型別(2)
  • Day 4:動態型別加弱型別不是罪——怎麼 JavaScript 一摔就變成個印度阿三?
  • Day 5:湯姆克魯斯與唐家霸王槍——變數的作用域(Scope) (1)
  • Day 6:湯姆克魯斯與唐家霸王槍——變數的作用域(Scope) (2)
  • Day 7:傳統 var 關鍵字的不足
  • Day 8:var 掰掰 —— ES6 更嚴謹安全的 let 和 const
  • Day 9:圖解變數作用域(Scope)
  • Day 10:程式也懂電梯向上? —— Hoisting
  • Day 11:Strict Mode (嚴謹模式)
  • Day 12:看 Strict Mode 如何施展「還我漂亮拳」(1)
  • Day 13:看 Strict Mode 如何施展「還我漂亮拳」(2)
  • Day 14:來挖挖恐龍骨 —— with 語法
  • Day 15:this 關鍵字 (1)
  • Day 16:this 關鍵字 (2)
  • Day 17:this 關鍵字 (3)
  • Day 18:this 關鍵字 (4)
  • Day 19:函數定義 (Function Definition) 的 100 種寫法
  • Day 20:ES6 的箭頭函數 (Arrow Functions)
  • Day 21:箭頭函數 (Arrow Functions) 的 this 和你想的不一樣 (1)
  • Day 22:箭頭函數 (Arrow Functions) 的 this 和你想的不一樣 (2)
  • Day 23:ES6 物件實字威力加強版 (Enhanced Object Literals)
  • Day 24:函數呼叫 (Function Invocation) 與立即函數 (Self-Invoking Functions)
  • Day 25:不是多了塊魚 —— 立即函數的應用整理
  • Day 26:程式界的哈姆雷特 —— Pass by value, or Pass by reference?
  • Day 27:別管變數 Pass by Whatever,尋找容易理解的銀色子彈 (Silver Bullet)
  • Day 28:閉包 (Closures)
  • Day 29:閉包 (Closures) 進階打怪實戰
  • Day 30:ES10 醞釀中 —— 擁抱 JS の 未來
Powered by GitBook
On this page
  • 嚴謹模式下你不能做的事 (續)
  • 8. 不能對不可刪除的屬性 (undeletable properties) 使用 delete 運算子
  • 9. 不能使用 eval 或 arguments 作為變數名稱
  • 10. 不能使用未來的保留字做變數名稱 (cannot use future reserved keywords as variables)
  • 11. 用 eval() 宣告的變數或函數,不能在該 Scope 被語法呼叫使用
  • 12. 不能使用 with 語法
  • 13. 全域執行環境內的函數,裡面的 this 代表的物件不一樣
  • 嚴謹模式下你還是能……
  • 1. 還是可以重複宣告變數
  • 總結
  • References

Was this helpful?

Day 13:看 Strict Mode 如何施展「還我漂亮拳」(2)

嚴謹模式下你不能做的事 (續)

8. 不能對不可刪除的屬性 (undeletable properties) 使用 delete 運算子

  • 一般模式下,delete 會回傳 false,但語法本身仍可以被接受。

  • 嚴謹模式下會直接拋錯。

錯誤類型:TypeError: Cannot delete property 'prototype' of function Object() { [native code] }

使用前:

console.log( delete Object.prototype ); // false

使用後:

"use strict";

console.log( delete Object.prototype ); // TypeError: Cannot delete property 'prototype' of function Object() { [native code] }

9. 不能使用 eval 或 arguments 作為變數名稱

  • eval 和 arguments 是 JavaScript 的關鍵字,各自另有用途,拿來作變數名稱容易導致非預期的結果。

錯誤類型:SyntaxError: Unexpected eval or arguments in strict mode

使用前:

function myFunc(){
    return arguments;
}

var arguments = 1500;
console.log(arguments);         // 1500
console.log(myFunc(1, 2, 3));   // Arguments Object [1, 2, 3]

使用後:

"use strict";

function myFunc(){
    return arguments;
}

var arguments = 1500;           // SyntaxError: Unexpected eval or arguments in strict mode
console.log(arguments);
console.log(myFunc(1, 2, 3));

10. 不能使用未來的保留字做變數名稱 (cannot use future reserved keywords as variables)

  • 有些字眼可能還不是當前 JavaScript 版本支援的關鍵字,但根據程式語言發展的經驗,有些字眼被預期很有機會在未來成為實際有作用的關鍵字。

  • 例如 interface、public、private、package 等,在其他程式語言都是很重要也很普遍的關鍵字。

  • 考慮到既有程式對未來 JavaScript 新版本的移植性 (portable),這些字眼就不適合用來作為變數名稱。

  • 以下是 W3Schools 列出的未來保留字,有些在 ES6 等後續版本已經成真:

    • implements

    • interface

    • let

    • package

    • private

    • protected

    • public

    • static

    • yield

錯誤類型:TypeError: Cannot assign to read only property 'articleTarget' of object '#<Object>'

使用前:

var public = 1500;
console.log(public);    // 1500

使用後:

"use strict";
var public = 1500;      // SyntaxError: Unexpected strict mode reserved word
console.log(public);

11. 用 eval() 宣告的變數或函數,不能在該 Scope 被語法呼叫使用

  • W3Schools 的原文是:For security reasons, eval() is not allowed to create variables in the scope from which it was called.

  • 但嚴格來說,並不是 eval() 宣告的時候拋錯,而是後續想使用的時候拋錯,而且拋出的錯誤類型是 ReferenceError。

  • 此外,如果是在 eval() 內自己宣告自己使用也沒有問題,後續想用語法去呼叫使用才會拋錯。

  • 所以這邊我的理解是:

    • 在嚴謹模式下,eval() 所執行的語法會自成一個暫時的 Scope,在裡面宣告的變數或函數都只屬於這個 Scope。

    • 所以後續用語法呼叫時,不認得該變數或函數,因而拋出 ReferenceError 類型的錯誤。

錯誤類型:ReferenceError: x is not defined

使用前(用於變數):

eval("var x = 123");
console.log(x);         // 123

使用後(用於變數):

"use strict";

eval("var x = 123");
console.log(x);         // ReferenceError: x is not defined

嚴謹模式下,在 eval() 內自己宣告自己使用並沒有問題:

"use strict";

var ret = 0;
eval("var n1 = 3, n2 = 6; ret = n1 + n2;");
console.log(ret);   // 9
console.log(n1);    // ReferenceError: n1 is not defined

使用前(用於函數):

eval("function myFunc(){ var x = 123; console.log(x); } myFunc();");
myFunc();
123
123

使用後(用於函數):

"use strict";

eval("function myFunc(){ var x = 123; console.log(x); } myFunc();");
myFunc();
123
ReferenceError: myFunc is not defined

12. 不能使用 with 語法

  • 完全禁止 with 語法。

錯誤類型:SyntaxError: Strict mode code may not include a with statement

使用前:

var x, y;
with (Math){
    x = cos(3 * PI) + sin(LN10);
    y = tan(14 * E);
};
console.log(x); // -0.2560196630425069
console.log(y); // 0.37279230719931067

使用後:

"use strict";

var x, y;
with (Math){   // SyntaxError: Strict mode code may not include a with statement
    x = cos(3 * PI) + sin(LN10);
    y = tan(14 * E);
};
console.log(x);
console.log(y);

13. 全域執行環境內的函數,裡面的 this 代表的物件不一樣

  • 一般模式下,全域執行環境內的函數裡面的 this,指的是 Global Object。

  • 嚴謹模式下,全域執行環境內的函數裡面的 this,變成 undefined。

使用前:

function myFunc(){
    console.log(this === window); // true
}
myFunc();

使用後:

"use strict";
function myFunc(){
    console.log(this === window); // false (`this` is `undefined`)
}
myFunc();

嚴謹模式下你還是能……

嚴謹模式下增加了很多規範,目的是讓程式更安全。

不過也不是盡善盡美,還是有遺珠。

1. 還是可以重複宣告變數

  • 這是一個很基本的不良語法,不過嚴謹模式並沒有加以控管。

"use strict";

var x = 10;
var x = 20;
console.log(x);     // 20

這部分會建議使用前面文章介紹過的 let 或 const 來取代 var,就可以限制變數重複宣告。

總結

嚴謹模式的使用情境相信還有很多,無法在幾篇文章的篇幅內全數囊括。但希望透過這三篇文章的介紹,能對嚴謹模式有一定深度的了解。

當專案規模越來越大,嚴謹的開發模式和程式撰寫方式才能讓專案更容易被多人維護,使用嚴謹模式是個必然的趨勢。

事實上可以注意到,著名的 JavaScript 編譯器 Babel 在將新版 ECMAScript 轉譯成 ES5 時,在你還沒打任何程式碼之前,ES5 的那一欄已經預設好一行程式,就是 use strict!

References

PreviousDay 12:看 Strict Mode 如何施展「還我漂亮拳」(1)NextDay 14:來挖挖恐龍骨 —— with 語法

Last updated 4 years ago

Was this helpful?

(Source: )

(Source: )

W3Schools - JavaScript Use Strict
Strict mode - JavaScript | MDN
with - JavaScript | MDN
【转载】JavaScript中with、this用法小结
[JavaScript] with的用法
Try it out - Babel · The compiler for next generation JavaScript
網路
Babel REPL