@@ -83,11 +83,116 @@ console.log(dreamapple.lastName); // King
83
83
```
84
84
是不是很方便呢?我们通过给` dreamapple ` 这个对象设置了属性` fullName ` 的` getter ` 和` setter ` 方法,就达到了我们想要的那种效果.
85
85
86
- 当然更好的一种方法就是使用` Object.defineProperty() ` 这个函数了,下面我们就来好好的探讨一下这个函数.
86
+ 当然更好的一种方法就是使用[ ` Object.defineProperty() ` ] [ 1 ] 这个函数了,下面我们就来好好的探讨一下这个函数.
87
+ 这个方法的作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性,并返回这个对象;我们先来看一下怎么使用这个方法:
88
+ ``` javascript
89
+ Object .defineProperty (obj, prop, descriptor)
90
+ ```
91
+ 其中参数` obj ` 表示的是需要定义属性的那个对象,参数` prop ` 表示需要被定义或者修改的属性名,
92
+ 参数` descriptor ` 就是我们定义的那个属性` prop ` 的描述;我们接下来主要讲解这个` descriptor ` .
93
+ 它是一个对象,它有许多的属性,我们接下来来分析这些属性都是干什么用的:
94
+
95
+ + ** value** 该属性对应的值,可以是任何有效的JavaScript值(数值,对象,函数等),默认为` undefined ` .我们可以看下面的一个小例子:
96
+ ``` javascript
97
+ var dream = {};
98
+ Object .defineProperty (dream, ' name' , {
99
+ value: ' dreamapple'
100
+ });
101
+
102
+ console .log (dream .name ); // dreamapple
103
+ dream .name = ' apple' ; // 修改name属性
104
+ console .log (dream .name ); // 并不是apple,依旧是dreamapple
105
+ ```
106
+ 从上面的代码中我们可以看到,我们给` dream ` 定义了一个新的属性` name ` ,然后我们打印出这个属性就是我们预期的那样,得到的是` dreamapple ` ;
107
+ 但是,当我们尝试改变这个属性的时候,却发现这个属性并没有改变,还以第一次我们赋给它的值;这是为什么呢?
108
+ 原来,只有当我们这个属性的` writable ` 修饰为` true ` 时,我们这个属性才可以被修改.
109
+
110
+ + ** writable** 当且仅当仅当该属性的` writable ` 为` true ` 时,该属性才能被赋值运算符改变;它的默认值为false.我们来修改一下上面的代码,
111
+ 让属性` name ` 可以被修改:
112
+ ``` javascript
113
+ Object .defineProperty (dream, ' name' , {
114
+ value: ' dreamapple' ,
115
+ writable: true
116
+ });
117
+
118
+ console .log (dream .name ); // dreamapple
119
+ dream .name = ' apple' ; // 修改name属性
120
+ console .log (dream .name ); // apple
121
+ ```
122
+ 我们可以看到,当我们把` writable ` 修改为` true ` 时,我们就可以修改` name ` 属性了.
123
+
124
+ + ** enumerable** 这个特性决定了我们定义的属性是否是可枚举的类型,默认是` false ` ;只有我们把它设置为` true ` 的时候这个属性才可以使用` for(prop in obj) ` 和` Object.keys() `
125
+ 中枚举出来.就像下面这样:
126
+ ``` javascript
127
+ Object .defineProperty (dream, ' a' , {
128
+ value: 1 ,
129
+ enumerable: false // 不可枚举
130
+ });
131
+ Object .defineProperty (dream, ' b' , {
132
+ value: 2 ,
133
+ enumerable: true // 可枚举
134
+ });
135
+
136
+ // 只会输出 b
137
+ for (prop in dream) {
138
+ console .log (prop);
139
+ }
87
140
141
+ console .log (Object .keys (dream)); // ['b']
88
142
143
+ console .log (dream .propertyIsEnumerable (' a' )); // false
144
+ console .log (dream .propertyIsEnumerable (' b' )); // true
145
+ ```
146
+ 所以当我们想给你个对象添加一个不可枚举的属性的时候,就应该把` enumerable ` 设置为` false ` .
89
147
148
+ + ** configurable** 这个特性决定了对象的属性是否可以被删除,以及除` writable ` 特性外的其它特性是否可以被修改;并且` writable ` 特性值只可以是` false `
149
+ 我们可以写一个代码示例来演示一下这个特性:
150
+ ``` javascript
151
+ Object .defineProperty (dream, ' c' , {
152
+ value: 3 ,
153
+ configurable: false
154
+ });
155
+ // throws a TypeError
156
+ Object .defineProperty (dream, ' c' , {
157
+ configurable: true
158
+ });
159
+ // throws a TypeError
160
+ Object .defineProperty (dream, ' c' , {
161
+ writable: true
162
+ });
163
+ // won't throws a TypeError
164
+ Object .defineProperty (dream, ' c' , {
165
+ writable: false
166
+ });
167
+ delete dream .c ; // 属性不可以被删除
168
+ console .log (dream .c ); // 3
169
+ ```
170
+ + ** get** 一个给属性提供` getter ` 的方法,如果没有` getter ` 则为` undefined ` ;该方法返回值被用作属性值,默认为undefined.
171
+ + ** set** 一个给属性提供` setter ` 的方法,如果没有` setter ` 则为` undefined ` ;该方法将接受唯一参数,并将该参数的新值分配给该属性,默认为undefined.
172
+ 知道了这些之后我们就可以使用更标准的一种方式去解决我们在文中开头的问题了:
173
+ ``` javascript
174
+ Object .defineProperty (dreamapple, ' fullName' , {
175
+ enumerable: true ,
176
+ get : function () {
177
+ return this .firstName + ' ' + this .lastName ;
178
+ },
179
+ set : function (fullName ) {
180
+ var names = fullName .trim ().split (' ' );
181
+ if (2 === names .length ) {
182
+ this .firstName = names[0 ];
183
+ this .lastName = names[1 ];
184
+ }
185
+ }
186
+ });
187
+ ```
188
+ 还有一点需要注意的是,` value ` 和` get,set ` 是不可以共存的,就是说你定义了` value ` 后就不能够再定义` get,set ` 特性了.
90
189
190
+ 好啦,今天的文章就写到这里了,相信大家对于` Object.defineProperty(obj, prop, descriptor) ` 这个方法应该掌握了;还有一点需要提及的是
191
+ 其实` Vue.js ` 的` 计算属性 ` 也是在这个函数的基础上进行的一些改进,详情可以看这里[ 计算属性的奥秘] [ 2 ] .
91
192
193
+ 如果你对这篇文章有什么意见或者建议可以在这里提出来[ issues] [ 3 ]
92
194
93
195
196
+ [ 1 ] :https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
197
+ [ 2 ] :http://cn.vuejs.org/guide/reactivity.html#计算属性的奥秘
198
+ [ 3 ] :https://github.com/dreamapplehappy/hacking-with-javascript/issues/3
0 commit comments