紅鵲豆網(wǎng)絡(luò)網(wǎng)站站建設(shè)營(yíng)銷思路八大要點(diǎn)
前言
ECMAScript 5首次引入嚴(yán)格模式的概念。嚴(yán)格模式用于選擇以更嚴(yán)格的條件檢查JavaScript代碼錯(cuò)誤,可以應(yīng)用到全局,也可以應(yīng)用到函數(shù)內(nèi)部。 嚴(yán)格模式的好處是可以提早發(fā)現(xiàn)錯(cuò)誤,因此可以捕獲某些 ECMAScript 問(wèn)題導(dǎo)致的編程錯(cuò)誤。
理解嚴(yán)格模式的規(guī)則非常重要,因?yàn)槲磥?lái)的 ECMAScript 會(huì)逐步強(qiáng)制全局使用嚴(yán)格模式。嚴(yán)格模式已得到所有主流瀏覽器支持。
1. 選擇使用
要選擇使用嚴(yán)格模式,需要使用嚴(yán)格模式編譯指示 (pragma),即一個(gè)不賦值給任何變量的字符串:
"use strict"
這樣一個(gè)即使在 ECMAScript 3 中也有效的字符串,可以兼容不支持嚴(yán)格模式的 JavaScript 引擎。支持嚴(yán)格模式的引擎會(huì)啟用嚴(yán)格模式,而不支持的引擎則會(huì)將這個(gè)編譯指示當(dāng)成一個(gè)未賦值的字符串字面量。
如果把這個(gè)編譯指示應(yīng)用到全局作用域,即函數(shù)外部,則整個(gè)腳本都會(huì)按照嚴(yán)格模式來(lái)解析。這意味著在最終會(huì)與其他腳本拼接為一個(gè)文件的腳本中添加了編譯指示,會(huì)將該文件中的所有JavaScript置于嚴(yán)格模式之下。
也可以像下面這樣只在一個(gè)函數(shù)內(nèi)部開啟嚴(yán)格模式:
function foo() {'use strict'console.log('CoderBin')// 其他代碼
}
如果你不能控制頁(yè)面中的所有腳本,那么建議只在經(jīng)過(guò)測(cè)試的特定函數(shù)中啟用嚴(yán)格模式。
2. 變量
嚴(yán)格模式下如何創(chuàng)建變量及何時(shí)會(huì)創(chuàng)建變量都會(huì)發(fā)生變化。第一個(gè)變化是不允許意外創(chuàng)建全局變量。在非嚴(yán)格模式下,以下代碼可以創(chuàng)建全局變量:
// 變量未聲明
// 非嚴(yán)格模式:創(chuàng)建全局變量
// 嚴(yán)格模式:拋出 ReferenceError
// 'use strict'
message = 'here is CoderBin'
雖然這里的 message
沒(méi)有前置 let 關(guān)鍵字,也沒(méi)有明確定義為全局對(duì)象的屬性,但仍然會(huì)自動(dòng)創(chuàng)建為全局變量。在嚴(yán)格模式下,給未聲明的變量賦值會(huì)在執(zhí)行代碼時(shí)拋出 ReferenceError
。
相關(guān)的另一個(gè)變化是無(wú)法在變量上調(diào)用delete 。在非嚴(yán)格模式下允許這樣,但可能會(huì)靜默失敗(返回false )。在嚴(yán)格模式下,嘗試刪除變量會(huì)導(dǎo)致錯(cuò)誤:
// 刪除變量
// 非嚴(yán)格模式:靜默失敗
// 嚴(yán)格模式:拋出 ReferenceError
// 'use strict'
let color = 'red'
delete color
嚴(yán)格模式也對(duì)變量名增加了限制。具體來(lái)說(shuō),不允許變量名為implements 、interface 、let 、package 、private 、protected 、public 、static 和yield 。這些是目前的保留字,可能在將來(lái)的ECMAScript版本中用到。如果在嚴(yán)格模式下使用這些名稱作為變量名,則會(huì)導(dǎo)致語(yǔ)法錯(cuò)誤。
3. 對(duì)象
在嚴(yán)格模式下操作對(duì)象比在非嚴(yán)格模式下更容易拋出錯(cuò)誤。嚴(yán)格模式傾向于在非嚴(yán)格模式下會(huì)靜默失敗的情況下拋出錯(cuò)誤,增加了開發(fā)中提前發(fā)現(xiàn)錯(cuò)誤的可能性。
首先,以下幾種情況下試圖操縱對(duì)象屬性會(huì)引發(fā)錯(cuò)誤。
- 給只讀屬性賦值會(huì)拋出 TypeError 。
- 在不可配置屬性上使用 delete 會(huì)拋出 TypeError 。
- 給不存在的對(duì)象添加屬性會(huì)拋出 TypeError 。
另外,與對(duì)象相關(guān)的限制也涉及通過(guò)對(duì)象字面量聲明它們。在使用對(duì)象字面量時(shí),屬性名必須唯一。例如:
// 兩個(gè)屬性重名
// 非嚴(yán)格模式:沒(méi)有錯(cuò)誤,第二個(gè)屬性生效
// 嚴(yán)格模式:拋出 SyntaxError
'use strict'
let person = {name: 'Coder',name: 'Bin'
}
這里的對(duì)象字面量 person 有兩個(gè)叫作 name 的屬性。第二個(gè)屬性在非嚴(yán)格模式下是最終的屬性。但在嚴(yán)格模式下,這樣寫是語(yǔ)法錯(cuò)誤。
注意:ECMAScript 6 刪除了對(duì)重名屬性的這個(gè)限制,即在嚴(yán)格模式下重復(fù)的對(duì)象字面量屬性鍵不會(huì)拋出錯(cuò)誤。
4. 函數(shù)
接下來(lái)讓我們看看嚴(yán)格模式對(duì)函數(shù)有哪些限制。
4.1 命名參數(shù)
首先,嚴(yán)格模式要求命名函數(shù)參數(shù)必須唯一??聪旅娴睦?#xff1a;
// 命名參數(shù)重名
// 非嚴(yán)格模式:沒(méi)有錯(cuò)誤,只有第二個(gè)參數(shù)有效
// 嚴(yán)格模式:拋出SyntaxError
function sum(num, num) {// 'use strict'// 函數(shù)代碼
}
在非嚴(yán)格模式下,這個(gè)函數(shù)聲明不會(huì)拋出錯(cuò)誤。這樣可以通過(guò)名稱訪問(wèn)第二個(gè) num ,但只能通過(guò) arguments
訪問(wèn)第一個(gè)參數(shù)。
4.2 arguments 對(duì)象
arguments 對(duì)象在嚴(yán)格模式下也有一些變化。在非嚴(yán)格模式下,修改命名參數(shù)也會(huì)修改 arguments 對(duì)象中的值。而在嚴(yán)格模式下,命名參數(shù)和 arguments 是相互獨(dú)立的。例如:
// 修改命名參數(shù)的值
// 非嚴(yán)格模式:arguments 會(huì)反映變化
// 嚴(yán)格模式:arguments 不會(huì)反映變化
function showValue(value) {// 'use strict'value = 'Foo'console.log(value)// "Foo"console.log(arguments[0])// 非嚴(yán)格模式:"Foo"// 嚴(yán)格模式:"Hi"
}
showValue('Hi')
在這個(gè)例子中,函數(shù) showValue()
有一個(gè)命名參數(shù) value 。調(diào)用這個(gè)函數(shù)時(shí)給它傳入?yún)?shù) “Hi” ,該值會(huì)賦給 value 。在函數(shù)內(nèi)部,value 被修改為"Foo" 。在非嚴(yán)格模式下,這樣也會(huì)修改 arguments[0]
的值, 但在嚴(yán)格模式下則不會(huì)。
4.3 arguments 對(duì)象屬性
另一個(gè)變化是去掉了 arguments.callee
和 arguments.caller
。在非嚴(yán)格模式下,它們分別引用函數(shù)本身和調(diào)用函數(shù)。在嚴(yán)格模式下,訪問(wèn)這兩個(gè)屬性中的任何一個(gè)都會(huì)拋出 TypeError 。例如:
// 訪問(wèn)arguments.callee
// 非嚴(yán)格模式:沒(méi)問(wèn)題
// 嚴(yán)格模式:拋出TypeError
function factorial(num) {// 'use strict'if (num <= 1) {return 1} else {return num * arguments.callee(num - 1)}
}
let result = factorial(5)
console.log(result)
類似地,讀或?qū)懞瘮?shù)的 caller 或 callee 屬性也會(huì)拋出 TypeError。 因此對(duì)這個(gè)例子而言,訪問(wèn) factorial.caller
和 factorial.callee
也會(huì)拋出錯(cuò)誤。
另外,與變量一樣,嚴(yán)格模式也限制了函數(shù)的命名,不允許函數(shù)名為 implements 、interface 、let 、package 、private 、 protected 、public 、static 和 yield 。
4.4 函數(shù)聲明
關(guān)于函數(shù)的最后一個(gè)變化是不允許函數(shù)聲明,除非它們位于腳本或函數(shù)的頂級(jí)。這意味著在 if 語(yǔ)句中聲明的函數(shù)現(xiàn)在是個(gè)語(yǔ)法錯(cuò)誤:
// 在if語(yǔ)句中聲明函數(shù)
// 非嚴(yán)格模式:函數(shù)提升至if語(yǔ)句外部
// 嚴(yán)格模式:拋出 ReferenceError
'use strict'
if (true) {function foo() {console.log('CoderBin')}
}
foo()
所有瀏覽器在非嚴(yán)格模式下都支持這個(gè)語(yǔ)法,但在嚴(yán)格模式下則會(huì)拋出語(yǔ)法錯(cuò)誤。
4.5 函數(shù)參數(shù)
ES6 增加了剩余操作符、解構(gòu)操作符和默認(rèn)參數(shù),為函數(shù)組織、結(jié)構(gòu)和定義參數(shù)提供了強(qiáng)大的支持。ECMAScript 7 增加了一條限制,要求使用任何上述先進(jìn)參數(shù)特性的函數(shù)內(nèi)部都不能使用嚴(yán)格模式,否則會(huì)拋出錯(cuò)誤。不過(guò),全局嚴(yán)格模式還是允許的。
// 可以
function foo(a, b, c) {'use strict'
}
// 不可以
function bar(a, b, c = 'd') {'use strict'
}
// 不可以
function baz({ a, b, c }) {'use strict'
}
// 不可以
function qux(a, b, ...c) {'use strict'
}
ES6增加的這些新特性期待參數(shù)與函數(shù)體在相同模式下進(jìn)行解析。如果允許編譯指示 “use strict” 出現(xiàn)在函數(shù)體內(nèi),JavaScrip t解析器就需要在解析函數(shù)參數(shù)之前先檢查函數(shù)體內(nèi)是否存在這個(gè)編譯指示,而這會(huì)帶來(lái)很多問(wèn)題。為此,ES7規(guī)范增加了這個(gè)約定,目的是讓解析器在解析函數(shù)之前就確切知道該使用什么模式。
5. eval() 函數(shù)
eval()
函數(shù)在嚴(yán)格模式下也有變化。最大的變化是 eval() 不會(huì)再在包含上下文中創(chuàng)建變量或函數(shù)。例如:
// 使用eval()創(chuàng)建變量
// 非嚴(yán)格模式:輸出10
// 嚴(yán)格模式:調(diào)用 console.log(x)時(shí)拋出 ReferenceError
function foo() {eval('let x = 10')console.log(x)
}
foo()
以上代碼在非嚴(yán)格模式下運(yùn)行時(shí),會(huì)在 foo() 函數(shù)內(nèi)部創(chuàng)建局部變量 x ,然后 console.log() 會(huì)輸出這個(gè)變量的值。在嚴(yán)格模式下,調(diào)用 eval() 不會(huì)在 foo() 中創(chuàng)建變量 x ,由于 x 沒(méi)有聲明, console.log() 會(huì)拋出 ReferenceError 。
變量和函數(shù)可以在 eval() 中聲明,但它們會(huì)位于代碼執(zhí)行期間的一個(gè)特殊的作用域里,代碼執(zhí)行完畢就會(huì)銷毀。因此,以下代碼就不會(huì)出錯(cuò):
'use strict'
let result = eval('let x = 10, y = 11; x + y')
console.log(result) // 21
這里在 eval() 中聲明了變量 x 和 y ,將它們相加后返回得到的結(jié)果。變量 result 會(huì)包含x 和y 相加的結(jié)果 21,雖然 x 和 y 在調(diào)用 console.log() 時(shí)已經(jīng)不存在了,但不影響結(jié)果的顯示。
6. eval() 和 arguments
嚴(yán)格模式明確不允許使用 eval 和 arguments 作為標(biāo)識(shí)符和操作它們的值。例如:
// 將 eval和 arguments 重新定義為變量
// 非嚴(yán)格模式:可以,沒(méi)有錯(cuò)誤
// 嚴(yán)格模式:拋出SyntaxError
// 'use strict'
let eval = 10
let arguments = 'Hello CoderBin!'
在非嚴(yán)格模式下,可以重寫 eval 和 arguments 。在嚴(yán)格模式下,這樣會(huì)導(dǎo)致語(yǔ)法錯(cuò)誤。不能用它們作為標(biāo)識(shí)符,這意味著下面這些情況都會(huì)拋出語(yǔ)法錯(cuò)誤:
- 使用let 聲明;
- 賦予其他值;
- 修改其包含的值,如使用++ ;
- 用作函數(shù)名;
- 用作函數(shù)參數(shù)名;
- 在try /catch 語(yǔ)句中用作異常名稱。
最后
整理了75個(gè)JS高頻面試題,并給出了答案和解析,基本上可以保證你能應(yīng)付面試官關(guān)于JS的提問(wèn)。
有需要的小伙伴,可以點(diǎn)擊下方卡片領(lǐng)取,無(wú)償分享