摘要:對只讀屬性賦值會報錯刪除不可配置的屬性會報錯只設置了取值器的屬性不可寫嚴格模式下,對一個只有取值器沒有存值器的屬性賦值,會報錯。嚴格模式禁止這種用法,全局變量必須顯式聲明。嚴格模式明確規定,函數內部使用將會報錯。
設計目的
啟用方法
顯式報錯
只讀屬性不可寫
只設置了取值器的屬性不可寫
禁止擴展的對象不可擴展
eval、arguments 不可用作標識名
函數不能有重名的參數
禁止八進制的前綴0表示法
增強的安全措施
全局變量顯式聲明
禁止 this 關鍵字指向全局對象
禁止使用 fn.callee、fn.caller
禁止使用 arguments.callee、arguments.caller
禁止刪除變量
靜態綁定
禁止使用 with 語句
創設 eval 作用域
arguments 不再追蹤參數的變化
向下一個版本的 JavaScript 過渡
非函數代碼塊不得聲明函數
保留字
參考鏈接
1.設計目的
明確禁止一些不合理、不嚴謹的語法,減少 JavaScript 語言的一些怪異行為。
增加更多報錯的場合,消除代碼運行的一些不安全之處,保證代碼運行的安全。
提高編譯器效率,增加運行速度。
為未來新版本的 JavaScript 語法做好鋪墊。
2.啟用辦法
"use strict";
2.1(1) 整個腳本文件
2.2(2)單個函數
use strict放在函數體的第一行,則整個函數以嚴格模式運行。
function strict() {
"use strict";
return "這是嚴格模式";
}
function strict2() {
"use strict";
function f() {
return "這也是嚴格模式";
}
return f();
}
function notStrict() {
return "這是正常模式";
}
2.3合并腳本
可以考慮把整個腳本文件放在一個立即執行的匿名函數之中。
(function () {
"use strict";
// some code here
})();
3.顯式報錯
3.1只讀屬性不可寫
嚴格模式下,設置字符串的length屬性,會報錯。
"use strict";
"abc".length = 5;
// TypeError: Cannot assign to read only property "length" of string "abc"
上面代碼報錯,因為length是只讀屬性,嚴格模式下不可寫。正常模式下,改變length屬性是無效的,但不會報錯。
嚴格模式下,對只讀屬性賦值,或者刪除不可配置(non-configurable)屬性都會報錯。
// 對只讀屬性賦值會報錯
"use strict";
Object.defineProperty({}, "a", {
value: 37,
writable: false
});
obj.a = 123;
// TypeError: Cannot assign to read only property "a" of object #
// 刪除不可配置的屬性會報錯
"use strict";
var obj = Object.defineProperty({}, "p", {
value: 1,
configurable: false
});
delete obj.p
// TypeError: Cannot delete property "p" of #
3.2只設置了取值器的屬性不可寫
嚴格模式下,對一個只有取值器(getter)、沒有存值器(setter)的屬性賦值,會報錯。
"use strict";
var obj = {
get v() { return 1; }
};
obj.v = 2;
// Uncaught TypeError: Cannot set property v of #
嚴格模式下,對禁止擴展的對象添加新屬性,會報錯。
"use strict";
var obj = {};
Object.preventExtensions(obj);
obj.v = 1;
// Uncaught TypeError: Cannot add property v, object is not extensible
上面代碼中,obj對象禁止擴展,添加屬性就會報錯
3.4eval、arguments 不可用作標識名
嚴格模式下,使用eval或者arguments作為標識名,將會報錯。下面的語句都會報錯。
"use strict";
var eval = 17;
var arguments = 17;
var obj = { set p(arguments) { } };
try { } catch (arguments) { }
function x(eval) { }
function arguments() { }
var y = function eval() { };
var f = new Function("arguments", ""use strict"; return 17;");
// SyntaxError: Unexpected eval or arguments in strict mode
3.5函數不能有重名的參數
正常模式下,如果函數有多個重名的參數,可以用arguments[i]讀取。嚴格模式下,這屬于語法錯誤。
function f(a, a, b) {
"use strict";
return a + b;
}
// Uncaught SyntaxError: Duplicate parameter name not allowed in this context
4.增強的安全措施
4.1全局變量顯式聲明
正常模式中,如果一個變量沒有聲明就賦值,默認是全局變量。嚴格模式禁止這種用法,全局變量必須顯式聲明。
"use strict";
v = 1; // 報錯,v未聲明
for (i = 0; i < 2; i++) { // 報錯,i 未聲明
// ...
}
function f() {
x = 123;
}
f() // 報錯,未聲明就創建一個全局變量
因此,嚴格模式下,變量都必須先聲明,然后再使用。
4.2禁止 this 關鍵字指向全局對象
正常模式下,函數內部的this可能會指向全局對象,嚴格模式禁止這種用法,避免無意間創造全局變量。
// 正常模式
function f() {
console.log(this === window);
}
f() // true
// 嚴格模式
function f() {
"use strict";
console.log(this === undefined);
}
f() // true
上面代碼中,嚴格模式的函數體內部this是undefined。
這種限制對于構造函數尤其有用。使用構造函數時,有時忘了加new,這時this不再指向全局對象,而是報錯。
function f() {
"use strict";
this.a = 1;
};
f();// 報錯,this 未定義
嚴格模式下,函數直接調用時(不使用new調用),函數內部的this表示undefined(未定義),因此可以用call、apply和bind方法,將任意值綁定在this上面。正常模式下,this指向全局對象,如果綁定的值是非對象,將被自動轉為對象再綁定上去,而null和undefined這兩個無法轉成對象的值,將被忽略。
// 正常模式
function fun() {
return this;
}
fun() // window
fun.call(2) // Number {2}
fun.call(true) // Boolean {true}
fun.call(null) // window
fun.call(undefined) // window
// 嚴格模式
"use strict";
function fun() {
return this;
}
fun() //undefined
fun.call(2) // 2
fun.call(true) // true
fun.call(null) // null
fun.call(undefined) // undefined
上面代碼中,可以把任意類型的值,綁定在this上面。
4.3禁止使用 fn.callee、fn.caller
函數內部不得使用fn.caller、fn.arguments,否則會報錯。這意味著不能在函數內部得到調用棧了。
function f1() {
"use strict";
f1.caller; // 報錯
f1.arguments; // 報錯
}
f1();
4.4禁止使用 arguments.callee、arguments.caller
arguments.callee和arguments.caller是兩個歷史遺留的變量,從來沒有標準化過,現在已經取消了。正常模式下調用它們沒有什么作用,但是不會報錯。嚴格模式明確規定,函數內部使用arguments.callee、arguments.caller將會報錯。
"use strict";
var f = function () {
return arguments.callee;
};
f(); // 報錯
4.5禁止刪除變量
嚴格模式下無法刪除變量,如果使用delete命令刪除一個變量,會報錯。只有對象的屬性,且屬性的描述對象的configurable屬性設置為true,才能被delete命令刪除。
"use strict";
var x;
delete x; // 語法錯誤
var obj = Object.create(null, {
x: {
value: 1, configurable: true
}
});
delete obj.x; // 刪除成功
5.靜態綁定
JavaScript 語言的一個特點,就是允許“動態綁定”,即某些屬性和方法到底屬于哪一個對象,不是在編譯時確定的,而是在運行時(runtime)確定的
嚴格模式對動態綁定做了一些限制。某些情況下,只允許靜態綁定。也就是說,屬性和方法到底歸屬哪個對象,必須在編譯階段就確定。這樣做有利于編譯效率的提高,也使得代碼更容易閱讀,更少出現意外。
5.1禁止使用 with 語句
嚴格模式下,使用with語句將報錯。因為with語句無法在編譯時就確定,某個屬性到底歸屬哪個對象,從而影響了編譯效果。
"use strict";
var v = 1;
var obj = {};
with (obj) {
v = 2;
}
// Uncaught SyntaxError: Strict mode code may not include a with statement
5.2創設 eval 作用域
正常模式下,JavaScript 語言有兩種變量作用域(scope):全局作用域和函數作用域。嚴格模式創設了第三種作用域:eval作用域。
eval所生成的變量只能用于eval內部。
(function () {
"use strict";
var x = 2;
console.log(eval("var x = 5; x")) // 5
console.log(x) // 2
})()
上面代碼中,由于eval語句內部是一個獨立作用域,所以內部的變量x不會泄露到外部。
注意,如果希望eval語句也使用嚴格模式,有兩種方式。
// 方式一
function f1(str){
"use strict";
return eval(str);
}
f1("undeclared_variable = 1"); // 報錯
// 方式二
function f2(str){
return eval(str);
}
f2(""use strict";undeclared_variable
5.3arguments 不再追蹤參數的變化
變量arguments代表函數的參數。嚴格模式下,函數內部改變參數與arguments的聯系被切斷了,兩者不再存在聯動關系。
function f(a) {
a = 2;
return [a, arguments[0]];
}
f(1); // 正常模式為[2, 2]
function f(a) {
"use strict";
a = 2;
return [a, arguments[0]];
}
f(1); // 嚴格模式為[2, 1]
上面代碼中,改變函數的參數,不會反應到arguments對象上來
6.向下一個版本的 JavaScript 過渡
6.1非函數代碼塊不得聲明函數
ES6 會引入塊級作用域。為了與新版本接軌,ES5 的嚴格模式只允許在全局作用域或函數作用域聲明函數。也就是說,不允許在非函數的代碼塊內聲明函數。
"use strict";
if (true) {
function f1() { } // 語法錯誤
}
for (var i = 0; i < 5; i++) {
function f2() { } // 語法錯誤
}
上面代碼在if代碼塊和for代碼塊中聲明了函數,ES5 環境會報錯。
注意,如果是 ES6 環境,上面的代碼不會報錯,因為 ES6 允許在代碼塊之中聲明函數。
6.2保留字
為了向將來 JavaScript 的新版本過渡,嚴格模式新增了一些保留字(implements、interface、let、package、private、protected、public、static、yield等)。使用這些詞作為變量名將會報錯。
function package(protected) { // 語法錯誤
"use strict";
var implements; // 語法錯誤
}
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/105782.html
摘要:綁定回調函數的對象前面的按鈕點擊事件的例子,可以改寫如下。方法有一些使用注意點。上面代碼中,方法會調用回調函數。但是,方法的回調函數內部的卻是指向全局對象,導致沒有辦法取到值。 4.1避免多層 this由于this的指向是不確定的,所以切勿在函數中包含多層的this。 var o = { f1: function () { console.log(this); var f2 = fu...
摘要:阿里巴巴資深技術專家毗盧毗盧,阿里巴巴資深技術專家,主導設計了框架,并基于該框架完成交易平臺架構升級改造,目前負責商品中心,專注電商領域業務建模與工程交付相結合的研究與平臺推廣。 摘要: 本文是《2017雙11交易系統TMF2.0技術揭秘》演講整理,主要講解了基于TMF2.0框架改造的交易平臺,通過業務管理域與運行域分離、業務與業務的隔離架構,大幅度提高了業務在可擴展性、研發效率以及可...
摘要:普通函數調用函數在全局作用域下運行在非嚴格模式下,指向全局對象,在嚴格模式下,會變成。使用來調用函數,或者說發生構造函數調用時,會自動執行下面的操作。即構造函數的指向它實例化出來的對象。 JavaScript中的this實際上是在函數被調用時發生的綁定,它指向什么完全取決于函數在哪里被調用。 先來列舉一下都有哪些函數調用方式: 普通函數調用 對象方法調用 call()、apply()...
閱讀 3300·2021-11-23 09:51
閱讀 2911·2021-10-28 09:33
閱讀 875·2021-10-08 10:04
閱讀 3682·2021-09-22 15:13
閱讀 1016·2019-08-30 15:55
閱讀 2906·2019-08-30 15:44
閱讀 564·2019-08-30 13:04
閱讀 2938·2019-08-30 12:56