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