可能很多人都知道最近很火的MVVM(model-view-virtualModel)框架,如Vue/Angular/React,如果你不知道的话,就要抓紧学习了,它能够把你从高频复杂的DOM解析中解脱出来。
MVVM框架的最主要的特性就是双向数据绑定,其中使用了ES5的getter/setter
函数,而他们就是对象的访问器属性,如果你不清楚它们的具体用法,那就不算是真正了解Javascript的基础知识对象的属性
,现在让我们一起回顾和总结下对象的属性。
对象
让我们先看下对象
的定义:
无序属性的集合,其属性可以包含基本值,对象或者函数。 ------ ECMA-262
也就是我们可以定义的对象属性只能是下面三种:
var person = {
// 属性
name: 'Nicholas',
// 对象
job: {
name: 'teacher',
salary: 10000
},
// 函数
greet: function () {
alert('hello');
}
};
对象的属性
JavaScript中只包含有两种属性:数据属性和访问器属性
,并包含不同的特征。
数据属性包含数据值的位置,可以在该位置对其进行读写。其包含4个特征:
configurable: 布尔值,表示能否通过delete属性来删除属性或修改属性的特性。
enumerable: 布尔值,是否能通过`for-in`循环或`Object.keys()`返回属性。
writable: 布尔值,属性值是否可以修改。
value: 属性的数据值,实质指向的是读写数据的位置。默认为undefined。
数据属性可以通过属性访问器(即点运算符和方括号计算表达式)来设置属性,也可以通过Object.defineProperty() 或 Object.defineProperties()
设置(下面统一用defineProperty代指两者)。而区别在于为布尔值的特征的默认值,通过属性访问器设置的默认都是true,而通过定义属性设置的默认都是false。
访问器属性不包含数据值,包含一对儿getter/setter
函数(非必须),在读取访问器属性时,调用getter函数,负责返回有效的值;在写入属性时,调用setter函数并传入新值,负责决定如何处理数据。其包含4个特征:
configurable: 布尔值,表示能否通过delete属性来删除属性或修改属性的特性,默认为false。
enumerable: 布尔值,是否能通过`for-in`循环或`Object.keys()`返回属性,默认为false。
get: 读取属性时调用的函数,默认为undefined。
set: 写入属性时调用的函数,接收唯一参数,默认为undefined。
访问器属性只能通过defineProperty
来定义。
如果属性已经存在,我们可以用defineProperty
再次修改该属性的特征,也可以通过Object.getOwnpropertyDescriptor() 或 Object.getOwnpropertyDescriptors()
来查看其特征列表。对于configurable = true
的属性我们也可以使用delete
操作符进行删除,如果设置成了不可配置的,我们就再也不能把它变回可配置的了。
属性访问器
有时我们会通过getter/setter
来代理一个属性的读取操作,即实现一个伪属性,但是这个属性不能与真实属性重名,否则会覆盖真实属性的值,变成动态获取,这可能不是你想要的结果。
// 实例:保存当前值变化的日志记录
var o = {
set current (str) {
this.log[this.log.length] = str;
},
get current () {
return this.log.join(',');
},
log: []
};
这样我们就代理current,用于保存实时日志,每次对log的更新也变成了一个操作历史档案,方便实时查看我们的所有改动。
同样我们可以在configurable配置为true的时候删除该属性的代理:delete o.current
。
关于delete,如果我们删除了一个var/let/const
属性,在其声明的作用域下会返回false,如果是严格模式,则会抛出语法错误。删除一个不可配置的属性同理会失败或报错。
删除数组的下标时,length并不会变小,遍历到该下标时会跳过执行。
影响configurable的方法
另外,存在一些Object的方法会影响到对象属性的可配置性:
- Object.freeze()
该方法可以冻结一个对象,冻结指的是不能向这个对象添加新的属性,不能修改其已有属性的值,不能删除已有属性,以及不能修改该对象已有属性的可枚举性、可配置性、可写性。也就是说,这个对象永远是不可变的。该方法返回被冻结的对象。
冻结指的是表层属性的浅冻结,如果需要冻结嵌套的属性,则需要遍历并递归冻结子属性。 - Object.preventExtensions()
该方法让一个对象变的不可扩展,也就是永远不能再添加新的属性。需要注意的是不可扩展的对象的属性通常仍然可以被删除,同时会阻止一个对象将__proto__属性重新指向另一个对象。 - Object.seal()
该方法可以让一个对象密封,并返回被密封后的对象。密封对象将会阻止向对象添加新的属性,并且会将所有已有属性的可配置性(configurable)置为不可配置(false),即不可修改属性的描述或删除属性。但是可写性描述(writable)为可写(true)的属性的值仍然被修改。
参考资料
- MDN - Object: https://developer.mozilla.org...
- JavaScript高级编程 - 对象类型
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。