基本规则

★ JS 对象属性的可枚举性将影响枚举(enumeration)的结果,如果属性的 enumerable 为 false,枚举时就不会取这个属性。
★ 枚举方式列举:for…in、Object.entries()、Object.keys()、Object.values()、JSON.stringify()、Object.assign()、展开运算符。
★ 通过常规赋值添加的属性都是可枚举的、可修改的、可删除的。
★ 内部属性和内部方法(如 constructor、[[Prototype]])默认都是不可枚举的。

分类与比较

♂ Object.assign() 与 展开运算符 的枚举特性一致,取对象自身的可枚举属性,包含Symbol 类型属性。
♂ 下面的枚举方式都不包含Symbol 类型属性。Object.getOwnPropertySymbols()用于枚举对象自身的仅 Symbol 类型属性。
♂ Object.entries()、Object.values() 与 Object.keys()的枚举特性一致。
♂ for…in 与 Object.keys() 的区别是:前者包含对象继承自原型对象的可枚举属性,而后者只包括对象自身的可枚举属性。
♂ JSON.stringify() 读取对象自身的可枚举属性,并忽略其中类型为 Undefined、Function、Symbol 的属性,并将属性和值序列化为 JSON 字符串。
♂ Object.getOwnPropertyNames() 获取对象自身的所有(包括可枚举和不可枚举)属性的名称。

配置与操作

♀ Object.defineProperty()
(1)用于为对象添加新属性或修改已有属性。
(2)函数用法 Object.defineProperty(obj , prop , descriptor ),其中 obj 是待添加或修改属性的对象,prop 是待添加或修改的属性名称,descriptor 是一个包含对属性描述的对象。descriptor 必然是”data descriptor”和”access descriptor”两种形式中的一种。
(3)”data descriptor”独有的属性:value(属性的值,默认为 undefined),writable(是否可写,默认为 false。不影响属性是否可被 delete。)
(4)”access descriptor”独有的属性:get(函数返回值作为属性的值,默认为 undefined)和 set(通过调用此函数改变 get 函数的返回值,默认为 undefined)
(5)”data descriptor”和”access descriptor”公有的属性:enumerable(可枚举性,默认为 false),configurable(descriptor 的类型是否可变并且属性是否可被 delete,默认为 false)。
(6)使用 Object.defineProperty 配置对象已有属性的同类 descriptor 时,支持增量。
♀ Object.getOwnPropertyDescriptor() 和 Object.getOwnPropertyDescriptors() 用于获取 descriptor 的内容。
♀ Object.preventExtensions() 阻止对象添加新的属性,对象也不再能改变[[Prototype]]的指向。
♀ Object.seal() 在 preventExtensions 的同时,也使对象所有已有属性的 configurable 为 false。
♀ Object.freeze() 在 preventExtensions 的同时,也使对象所有已有属性的 configurable 和 writable 为 false。但通过”access descriptor”定义的属性仍然可赋值。

实例 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
function A(){
this.va=1;
}
A.prototype.vb=2;
var a= new A();
Object.defineProperty(a, "vc", {value:3});

var inArr= [];
for(var para in a)
{
inArr.push(para);
}

console.log(Object.keys(a)); // ["va"]
console.log(Object.getOwnPropertyNames(a)); // ["va", "vc"]
console.log(JSON.stringify(a)); // {"va":1}
console.log(inArr); // ["va", "vb"]

a["vc"]= 8;
console.log(a["vc"]); // 3

delete a["vc"]; // delete将返回false
console.log(a["vc"]); // 3

Object.defineProperty(a, "vd", {value:4, writable: true});

a["vd"]= 8;
console.log(a["vd"]); // 8

delete a["vd"]; // delete将返回false
console.log(a["vd"]); // 8

Object.defineProperty(a, "ve", {value:4, configurable: true});

a["ve"] = 2;
console.log(a["ve"]); // 4

Object.defineProperty(a, "ve", {writable:true});

console.log(a["ve"]); // 4
a["ve"] = 2;
console.log(a["ve"]); // 2
delete a["ve"]; // delete将返回true
console.log(a["ve"]); // undefined

实例 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Person(name){
this.name = name;
}
Person.prototype.getName = function(){
return this.name ;
};
function Stuff1(name, id){
this.name = name;
this.id = id;
}
for(var fn in Person.prototype){
Stuff1.prototype[fn] = Person.prototype[fn];
}
var piupiu1 = new Stuff1("piupiu1","008");
console.log(piupiu1.constructor === Stuff1);//打印true
解析:Person.prototype的三个属性(constructor, getName, [[Prototype]]),仅有getName属性可枚举,于是Stuff1.prototype仅仅继承了“getName”属性,打印的constructor仍是自己的。