这章要来探讨物件的属性
前几个章节有针对物件的原形、物件的本身还有函式做了一些解析。
那么就由这章来解析物件属性的特徵,也会解释原生的原形以及我们自己定义的原形有甚么不一样的地方喔!
以及框架是如何利用物件属性的特徵来开发出特别的功能!
var person = { a: 1, b: 2, c: 3};console.log(person);
如上,印出来之后可以得到下面的结果
就可以看到 person 这个物件里面的属性 a、b、c以及对应的值,还有物件的原形连结到哪里。
我们都知道,修改物件里面属性的值可以是 person.a = 4
或是 person['a'] = 4
,这两种方法都可以。
那么今天就要教大家另外一种进阶的方法,叫做 Object.defineProperty。
这个方法除了可以调整属性的值(value)之外,还可以调整属性的特徵喔!
而上述的两种方法都只能调整属性的其中一个特徵,也就是属性对应的值(value)。
让我们接着看~属性到底有那些特徵的?
值(value) => 对应的值是甚么可否写入(writable) => 可否进行属性质的修改可否被删除(configurable) => 可否可以用 delete 删除属性可否被列举(enumerable) => 可否利用 for...in 迴圈 将物件属性列举出来,可以限制特定的属性是否被列举出来那我们就实际来看看要怎么运用 Object.defineProperty!
Object.defineProperty(物件的变数,或是物件本人, 要修改的属性名称(字串), { writable: 布林值, configurable: 布林值, value: 要修改或是赋予甚么值, enumerable: 布林值});Object.defineProperty(person, 'a', { writable: true, configurable: true, value: 4, enumerable: true});
也不一定每次每个属性特徵都要列出来,也可以只修改一种
Object.defineProperty(person, 'a', { configurable: false,});
那我们实际来操作看看
var person = { a: 1, b: 2, c: 3};console.log(person);Object.defineProperty(person, 'a', { writable: true, configurable: true, value: 4, enumerable: true});console.log(person);
我们会发现,虽然一开始 a 的值还是 1 ,但是展开以后还是4,所以他会显示已经变化过后的值。
那我们再来修改其他的属性看看!
Object.defineProperty(person, 'a', { configurable: false,});
那我们实际来操作看看
var person = { a: 1, b: 2, c: 3};console.log(person);Object.defineProperty(person, 'a', { writable: false, configurable: true, value: 4, enumerable: true});person.a = 5;console.log(person);
我们把 writable 改成 false,代表我们没有办法再重新修改 a 属性的 value 。
所以我们利用 Object.defineProperty 把 a 的属性改成 4 之后,并且把 writable 改成 false。
后面的 person.a = 5;
就没办法再进行修改的动作了!
但其实这样的状况会是一个静默的错误喔!
也就是在非严格模式下(Sloppy mode),不会显示错误红字,但是如果切换到严格模式的话,就会有错误讯息产生。
var person = { a: 1, b: 2, c: 3};console.log(person);Object.defineProperty(person, 'a', { writable: false, configurable: true, value: 4, enumerable: true});person.a = 5;(function () { 'use strict'; person.a = 5;})();console.log(person);
同时也会导致最后面的 console.log 不会执行喔!
所以在严格模式的时候要特别注意。
那接着我们针对 b 的属性来试试看不同的属性操作
var person = { a: 1, b: 2, c: 3};console.log(person);Object.defineProperty(person, 'a', { writable: false, configurable: true, value: 4, enumerable: true});person.a = 5;// (function () {// 'use strict';// person.a = 5;// })();Object.defineProperty(person, 'b', { configurable: false,});delete person.a;delete person.b;console.log(person);
这边有看到吗? 在我设定 b 的 configurable 属性为 false 后,b的属性就无法被 delete 语法给删除,但a就成功被删除噜~!
那介绍最后一个 enumerable 的属性套用在属性 c 身上,并且我们先不删除 a 属性,透过for in 的迴圈显示物件person的属性名称:
var person = { a: 1, b: 2, c: 3};console.log(person);Object.defineProperty(person, 'a', { writable: false, configurable: true, value: 4, enumerable: true});person.a = 5;// (function () {// 'use strict';// person.a = 5;// })();Object.defineProperty(person, 'b', { configurable: false,});// delete person.a;delete person.b;// Object.defineProperty(person, 'c', {// enumerable: false,// });for (var key in person) { console.log('列举: ' + key);}console.log(person);
最后我们再把注解拿掉
var person = { a: 1, b: 2, c: 3};console.log(person);Object.defineProperty(person, 'a', { writable: false, configurable: true, value: 4, enumerable: true});person.a = 5;// (function () {// 'use strict';// person.a = 5;// })();Object.defineProperty(person, 'b', { configurable: false,});delete person.a;delete person.b;Object.defineProperty(person, 'c', { enumerable: false,});for (var key in person) { console.log('列举: ' + key);}console.log(person);
你就可以看到, a 因为被删掉了无法被列举,b 可以被列举但不能写入,c 还在但不能被列举。
所以被列举出来的只有 b 属性。
以上就是关于Object.defineProperty的用法,以及4个属性特徵的介绍!
那么除了修改以外,其实Object.defineProperty也可以做到新增的动作喔!
var person = { a: 1, b: 2, c: 3};console.log(person);Object.defineProperty(person, 'a', { writable: false, configurable: true, value: 4, enumerable: true});person.a = 5;// (function () {// 'use strict';// person.a = 5;// })();Object.defineProperty(person, 'b', { configurable: false,});delete person.a;delete person.b;Object.defineProperty(person, 'c', { enumerable: false,});for (var key in person) { console.log('列举: ' + key);}Object.defineProperty(person, 'd', { writable: false, value: {},});person.d = 6;console.log(person);
在这边我们新增了属性 'd' 到 person这个物件里面,并且给予不可写入的特徵,他的值我们给予空物件。
当然 person.d = 6;
就又会是一个 静默错误 并且不能够进行修改。
但是当我们今天是针对它里面的值做额外的设定的话,还是有办法赋予到内层物件的值喔!
var person = { a: 1, b: 2, c: 3};console.log(person);Object.defineProperty(person, 'a', { writable: false, configurable: true, value: 4, enumerable: true});person.a = 5;// (function () {// 'use strict';// person.a = 5;// })();Object.defineProperty(person, 'b', { configurable: false,});delete person.a;delete person.b;Object.defineProperty(person, 'c', { enumerable: false,});for (var key in person) { console.log('列举: ' + key);}Object.defineProperty(person, 'd', { writable: false, value: {},});person.d = 6;person.d.a = 6;console.log(person);
这也是特别要注意的点,就是以上这4个物件的特徵,都是属于浅层的控制,深层的控制则需要另外再进行设定喔!
最后在介绍,因为刚刚我们都是一个一个属性设定,有些人会觉得这样很麻烦,我设定一个属性就要写一长串,这里就要介绍同时设定很多属性的方法,那就是Object.defineProperties!
用这个方法就可以同时设定很多的属性噜!
Object.defineProperties(物件变数或物件本人, { 物件属性名称1: { 特徵1: xx 特徵2: xx 特徵3: xx 特徵4: xx }, 物件属性名称2: { 特徵1: xx 特徵2: xx 特徵3: xx 特徵4: xx },...});Object.defineProperties(person, { a: { writable: false, configurable: true, value: 4, enumerable: true }, b: { configurable: false, }, c: { enumerable: false, }, d : { writable: false, value: {} }});
下面的就是依照这篇文章刚刚练习的内容一次进行设定的写法,大家也可以试试看设定不同的属性喔!
那么没问题的话就往下一篇文章迈进~汪汪!