前段时间开始了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
// 确认非声明变量在创建后,为全局对象的属性
参考: