前段時間開始了JS的學習,第一個重要的知識點就是變量聲明及變量聲明提升。關于變量聲明,有這樣兩種代碼:
var a = 1;
console.log(a) // 1
a = 1 ;
console.log(a) // 1
var a = 1
,a = 1
都沒有報錯的,那么這兩者區別在哪里呢?
首先,var
語句用于聲明變量,而不使用var
直接賦值,則會創建一個全局變量,該變量是全局對象的一個屬性。
如上面第2段代碼,在全局作用域下,對非聲明的變量a
賦值,會創建一個全局變量a
,在瀏覽器中,a
為window
對象的一個屬性。
以上我們了解了非var a
的基本構成,他們之間還有什么區別呢?
- 非聲明變量沒有變量提升,且只有在執行賦值操作時才被創建
console.log(a) // ReferenceError: a is not defined
a = 1
console.log(a) // 1
- 聲明變量作用域限制在其聲明位置的上下文中,非聲明變量在創建后是全局的
function f() {
a = 1
var b = 2
}
f() //執行方法,創建變量
console.log(a) // 1
console.log(b) // ReferenceError: b is not defined
//這里可以看出,聲明變量的作業域是有限制的,而非聲明變量在創建后會成為全局變量
- 聲明變量是它所在上下文環境的不可配置屬性(non-configurable property),非聲明變量是可配置的(例如非聲明變量可以被刪除)。
a = 2
var b = 2
var testa = Object.getOwnPropertyDescriptor(window, 'a')
var testb = Object.getOwnPropertyDescriptor(window, 'b')
// 在chrome下,使用Object.getOwnPropertyDescriptor方法對a和b 檢驗
console.log(testa) // Object {value: 2, writable: true, enumerable: true, configurable: true}
console.log(testb) // Object {value: 2, writable: true, enumerable: true, configurable: false}
/*
Object.getOwnPropertyDescriptor()會返回對應第一個參數的對象的屬性描述符(property description),
如果指定的屬性不在對象上,會返回undefined,
可以看出在全局作用域下,聲明變量和非聲明變量都為全局對象window的屬性。
其區別是聲明變量的configurable為true,非聲明變量的configurable為false。
*/
delete(a) // true 可以刪除
delete(b) // false 不可以刪除
console.log(a) // ReferenceError: a is not defined
console.log(b) // 2
// 根據configurable屬性,非聲明變量a 可以被操作,而聲明變量a不可以
function ccc () {
c = 1
}
var ddd = {}
var testc = Object.getOwnPropertyDescriptor(window, 'c')
console.log(testc) // undefined
ccc()
var testc = Object.getOwnPropertyDescriptor(window, 'c')
var testd = Object.getOwnPropertyDescriptor(ddd, 'c')
console.log(testc) // Object {value: 1, writable: true, enumerable: true, configurable: true}
console.log(testd) // undefined
// 確認非聲明變量在創建后,為全局對象的屬性
參考: