达到完美境界并不是无以复加,而是无可去除。——<安托万·德·圣·埃克苏佩里>
可以在 Javascript
中配置对象属性,例如将属性设置为伪私有或只读。这个特性从ECMAScript 5.1
开始就可用了,因此所有最新的浏览器都支持它。
要做到这一点,你需要像这样使用Object
原型的defineProperty
方法:
1 | var a = {}; |
语法如下:
1 | Object.defineProperty(dest, propName, options) |
或者对于多个定义:
1 | Object.defineProperties(dest, { |
其中选项包括以下属性:
- Value: 如果属性不是
getter
(见下文),Value
是一个强制属性。{a: 12} === Object.defineProperty(obj, 'a', {value: 12})
- 可写: 设置为只读。注意,如果属性是嵌套对象,那么它的属性仍然是可编辑的。
- 枚举: 将属性设置为
hidden
。这意味着for ... of
循环和stringify
不会在结果中包含属性,但是属性仍然在那里。注意:这并不意味着财产是私有的!它仍然可以从外部访问,这只是意味着它不会被打印。 - 可配置的: 将属性设置为不可修改的,例如,不允许删除或重定义。同样,如果属性是嵌套对象,则其属性仍然是可配置的。
因此,为了创建私有常量属性,您可以像这样定义它:
1 | Object.defineProperty(obj, 'myPrivateProp', {value: val, enumerable: false, writable: false, configurable: false}); |
除了配置属性外,由于第二个参数是字符串,defineProperty
还允许我们定义动态属性。例如,假设我要根据一些外部配置创建属性:
1 | var obj = { |
但这还不是全部!像其他OOP语言一样,高级属性使我们能够创建getter和setter
!在这种情况下,不能使用 writable,enumerable和configurable
性能,而是:
1 | function Foobar () { |
除了封装和高级访问器的明显优势外,您还会注意到我们没有“调用”该吸气剂,而是仅“获取”了该属性而没有括号!这太棒了!例如,假设我们有一个带有长嵌套属性的对象,如下所示:
1 | var obj = {a: {b: {c: [{d: 10}, {d: 20}] } } }; |
现在,我们无需创建a.b.c[0].d(其中一个属性可以解决undefined并引发错误),而可以创建一个别名:
1 | Object.defineProperty(obj, 'firstD', { |
总结
如果您定义了一个没有 setter的getter并且仍然尝试设置一个值,那么您将得到一个错误!当使用诸如 $.extend
或的辅助功能时,这一点尤其重要 _.merge
。小心!
参考
- https://www.jstips.co/en/javascript/advanced-properties/
- MDN - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
- https://bdadam.com/blog/defining-properties-in-javascript.html
关注【公众号】,了解更多。
赞赏一下 坚持原创技术分享,您的支持将鼓励我继续创作!