众所周知,通常在遍历JS中的对象的时候,一般会使用for...in或者Object.keys()方法,同时要注意属性的enumerable设置。

在ES5中,我们定义一个类的写法如下:

1
2
3
4
5
6
7
function Person(name) {
this.name = name;
Person.prototype.say = function () {
console.log(name);
};
}
var p = new Person('Shinji');

使用for...in遍历对象p可以看到输出了namesay,因为for...in会遍历所有自己包括原型链上的可枚举属性,所以不仅输出了name,也输出了say

在ES6之后,定义一个类可以直接使用class:

1
2
3
4
5
6
7
8
9
class Person {
constructor(name) {
this.name = name;
}
say() {
console.log(this.name);
}
}
const p = new Person('Shinji');

同样使用for...in遍历对象p,只得到了name
使用Object.getOwnPropertyDescriptors(Object.getPrototypeOf(p))可以看到constructorsayenumerable属性都是false,所以使用for...in遍历不出来。使用Object.getOwnPropertyNames(Object.getPrototypeOf(p))可以得到["constructor", "say"],可以用来获取对象p拥有的方法,如果有继承,则需要再嵌套一层getPrototypeOf

在TypeScript中,定义一个类和es6差不多:

1
2
3
4
5
6
7
8
9
10
class Person {
name: string;
constructor(name: string) {
this.name = name;
}
say() {
console.log(this.name);
}
}
let p = new Person('Shinji');

但在使用for...in遍历的时候,发现和es5的输出差不多,其实是因为编译选项中将target设置为了ES5,编译后的代码和上面es5的代码差不多,所以sayenumerable为true,如果设置targetESNEXT,则就和es6的表现差不多了。
总之,TypeScript和ES6的class并不一样,毕竟TypeScript还是需要编译成JavaScript的。但是如果是使用babel将ES6的class编译到es5,say()enumerable会设置为false