[JavaScript] Strict Mode
ECMAScript 5的Strict Mode不是ECMAScript 的子集。
Strict Mode 執行上跟Non-Strict Mode下有明顯差異。
Strict Mode 跟Non-Strict Mode可並存。
Strict Mode 將JavaScript再執行一些陷阱語法直接丟明顯的錯誤。
Strict Mode 修正JavaScript Engine難以優化的錯誤。
Strict Mode 禁止了一些未來ECMAScript可能會使用的關鍵字。
開啟Strict Mode
"use strict";
- 放在語法前。
- 不要將”use strict”用在{}使用,他會失去效果。
{
"use strict";
}
- 可以在function scope開啟strict mode。
!function strict() {
"use strict";
function nested() {return "So am I!";}
return "I am strict mode "+ nested();
}();
!function nonStrict() {return "I am non Strict";}();
Strict Mode執行上的不同
- 拼寫錯誤的變數(或沒有宣告就存取的變數)會拋出異常。
"use strict";
var nAme;
nEme = 17; // ReferenceError
- Silently Fail (程式碼執行不報錯也沒有效果的錯誤)會拋出異常。
"use strict";
var obj1 = {};
Object.defineProperty(obj1, "x", {value: 42, writeable: false}});
obj1.x = 9; //TypeError
var obj2 = {get x(){return 17;}};
obj2.x = 5; // TypeError
var fixed = {};
Object.preventExtensions(fixed);
fixed.newProp = "ohai"; // TypeError
- 試圖刪除不可刪除之屬性會拋出異常
"use strict";
delete Object.prototype; // TypeError
- Gecko 34以前下方指令會丟出錯誤(ECMAScript6不存在)
"use strict";
var o = {p:1, p:2};
- 函數的參數要唯一
function sum(a, a, c) {
"use strict";
return a+b+c;
}
- 禁止八進位語法
var a = 0o10;
parseInt(a);
"use strict";
var sum = 015 + // SyntaxError
197 +
142;
- 禁止設置primitive值屬性
!function() {
"use strict";
false.true = ""; //TypeError
(14).sailing = "home"; //TypeError
"with".you = "far away"; //TypeError
}();
簡化變數(variable)的使用
- 禁止使用with
"use strict";
var x = 17;
with (obj) // SyntaxError
{
x; // x mean obj.x or var x? it will make engine can not process optimization.
}
- Strict Mode下的eval不在讓surrounding scope(包圍eval的scope),注入新變數。例如eval(‘var’)
function a () {
eval('var x=10');
console.log(x); //x will be create.
}
var x = 17;
var evalX = eval("'use strict'; var x = 42; x"); //this x !== var x=17
console.assert(x === 17);
console.assert(evalX === 42);
2.1 如果eval在Strict Mode下面執行,其代碼會被當作在Strict Mode下為執行。
function strict1(str) {
'use strict';
return eval(str); // str will be treated as strict mode code
}
function strict2(f, str) {
'use strict';
return f(str); // not eval(...): str is strict if and only
// if it invokes strict mode
}
function nonstrict(str) {
return eval(str); // str is strict if and only
// if it invokes strict mode
}
strict1("'Strict mode code!'");
strict1("'use strict'; 'Strict mode code!'");
strict2(eval, "'Non-strict code.'");
strict2(eval, "'use strict'; 'Strict mode code!'");
nonstrict("'Non-strict code.'");
nonstrict("'use strict'; 'Strict mode code!'");
- Strict Mode禁止刪除變數
'use strict';
var a={x:10};
delete a.x; // It can delete
var x;
delete x; // SyntaxError
eval('var y; delete y;'); // SyntaxError
簡化eval跟arguments
- 對eval跟arguments誤用的範例如下
"use strict";
eval = 17;
arguments++;
++eval;
var obj = { set p(arguments) { } };
var eval;
try { } catch (arguments) { }
function x(eval) { }
function arguments() { }
var y = function eval() { };
var f = new Function("arguments", "'use strict'; return 17;");
- Strict Mode 函數arguments的值,不會隨著參數變數被修改而跟著改變。
function f(a){
"use strict";
a = 42; //a 改變,但是函數的arguments仍是f(17);
return [a, arguments[0]];
}
var pair = f(17);
console.assert(pair[0] === 42);
console.assert(pair[1] === 17);
- 不再支援arguments.callee (為了最佳化)
"use strict";
var f = function() { return arguments.callee; };
f(); // TypeError
安全的 JavaScript
- Strict Mode下回傳this將不再將整個this包裝(boxed)返回出去,而是undefined, 或是call, apply, bind的this。一般模式下會將this回傳出去,可能會包含許多額外資訊(ex window 物件),同時也有助效能提升。
- 這也意味瀏覽器將不能透過Strict Mode下的function 回傳this來取得window物件捕捉額外資訊。
'use strict';
function fun() { return this; }
console.assert(fun() === undefined);
console.assert(fun.call(2) === 2);
console.assert(fun.apply(null) === null);
console.assert(fun.call(undefined) === undefined);
console.assert(fun.bind(true)() === true);
- Strict Mode下的arguments不再提供”walk” to JavaScript Stack的下面兩個方式 function.caller(誰呼叫我)跟function.arguments(呼叫我的函式的參數),因為這會導致不安全的存取。
function restricted()
{
"use strict";
restricted.caller; // TypeError
restricted.arguments; // TypeError
}
function privilegedInvoker()
{
return restricted();
}
privilegedInvoker();
- Strict Mode下的arguments不再提供這個函數相關變數的存取方式,例如arguments.caller。這個在現在許多瀏覽器都已經不再存取的到。
'use strict';
function fun(a, b) {
'use strict';
var v = 12;
return arguments.caller; // throws a TypeError
}
fun(1, 2); // doesn't expose v (or a or b)
保留ECMAScript未來擴充的關鍵字
- 關鍵字範例如下
implements, interface, let, package, private, protected, public, static, yield
function package(protected){ // !!!
"use strict";
var implements; // !!!
interface: // !!!
while (true)
{
break interface; // !!!
}
function private() { } // !!!
}
function fun(static) { 'use strict'; } // !!!
- Strict Mode也禁止了Function Declaration 一些的宣告方式,這也是未來ECMAScript會制訂函式宣告式未來的一些規範。
'use strict';
if (true)
function f() { } // SyntaxError
for (var i = 0; i < 5; i++)
function f2() { } // SyntaxError
function baz() { // ok
function eit() { } // ok
}
沒有留言:
張貼留言