本文简介
ES6
刚推出的时候,let
和 const
应该是大多数人学习 ES6
的第一个知识点。
其中 const
可以用来定义 常量 ,将不需要改变的数据定义成一个常量。
但其实在 ES6
之前我们也是有办法定义常量的。
ES 5 创建常量
Object.defineProperty
的基础用法
在 ES6
之前是没有 const
的,如果需要定义常量,可以使用 Object.defineProperty
。
很多人知道 Vue2
使用 Object.defineProperty
监听数据变化,但不一定知道 Object.defineProperty
也可以用来定义常量。
Object.defineProperty
方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
Object.defineProperty(obj, prop, descriptor)
接收3个参数
- obj: 要定义属性的对象。
- prop: 要定义或修改的属性的名称或
Symbol
。 - descriptor: 要定义或修改的属性描述符。
举个例子
代码语言:javascript复制var LH = {}
Object.defineProperty(LH, 'name', {
value: '雷猴'
})
console.log(LH) // 输出: {name: '雷猴'}
LH.name = '鲨鱼辣椒'
console.log(LH) // 输出: {name: '雷猴'}
复制代码
可以将上面的代码放到你的浏览器里试试。
为什么修改 LH.name
无效呢?因为 descriptor
除了 value
之外,还有其他属性,比如 writable
就可以用来定义该对象是否允许被修改,默认是 false
,也就是不能修改。
所以 LH.name = '鲨鱼辣椒'
修改无效。
如果将 writable
改成 true
就可以修改了
var LH = {}
Object.defineProperty(LH, 'name', {
value: '雷猴',
writable: true // 允许修改
})
console.log(LH) // 输出: {name: '雷猴'}
LH.name = '鲨鱼辣椒'
console.log(LH) // 输出: {name: '鲨鱼辣椒'}
复制代码
创建常量
顺着上面的思路,如果我们把 LH
改成 window
,那是不是就可以在 window
上定义一个属性,而且该属性是全局的,定义后在什么地方都能调用。
Object.defineProperty(window, 'NAME', {
value: '雷猴'
})
console.log(NAME) // 输出: 雷猴
NAME = '鲨鱼辣椒'
console.log(NAME) // 输出: 雷猴
window.NAME = '蟑螂恶霸'
console.log(NAME) // 输出: 雷猴
复制代码
不管如何修改,NAME
都是最开始定义的值。
常量居然可以修改值?
上面创建的常量,value
是一个基础数据类型的值。如果换成引用类型的值,那内容是可以修改的。
Object.defineProperty(window, 'NAME', {
value: {
nickname: '雷猴'
}
})
console.log(NAME)
NAME.nickname = '鲨鱼辣椒'
console.log(NAME)
复制代码
原因是,常量锁定的是定义时所指向的内存地址。
定义基础数据类型时,内存地址直接指向那个值。但定义引用类型时,内存地址存的是引用地址。所以常量的定义指的是引用地址不能修改。
兼容性
使用 Object.defineProperty
定义常量时需要注意兼容性