
    除了for/in循环之外,ECMAScript 5定义了两个用以枚举属性名称的函数。第一个是Object.keys(), 它返回一个数组,这个数组由对象中可枚举的自有属性的名称组成。
语法:
Object.keys(obj)
参数
obj
    要返回其枚举自身属性的对象。
返回值
一个表示给定对象的所有可枚举属性的字符串数组。
描述
Object.keys 返回一个所有元素为字符串的数组,其元素来自于从给定的object上面可直接枚举的属性。这些属性的顺序与手动遍历该对象属性时的一致。
例子:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | var arr = ['a', 'b', 'c'];
 console.log(Object.keys(arr));
 
 
 var obj = { 0: 'a', 1: 'b', 2: 'c' };
 console.log(Object.keys(obj));
 
 
 var anObj = { 100: 'a', 2: 'b', 7: 'c' };
 console.log(Object.keys(anObj));
 
 | 
    要在原生不支持的旧环境中添加兼容的Object.keys,请复制以下代码段
| 12
 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
 
 | if (!Object.keys) {Object.keys = (function () {
 var hasOwnProperty = Object.prototype.hasOwnProperty,
 hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
 dontEnums = [
 'toString',
 'toLocaleString',
 'valueOf',
 'hasOwnProperty',
 'isPrototypeOf',
 'propertyIsEnumerable',
 'constructor'
 ],
 dontEnumsLength = dontEnums.length;
 
 return function (obj) {
 if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) throw new TypeError('Object.keys called on non-object');
 
 var result = [];
 
 for (var prop in obj) {
 if (hasOwnProperty.call(obj, prop)) result.push(prop);
 }
 
 if (hasDontEnumBug) {
 for (var i=0; i < dontEnumsLength; i++) {
 if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i]);
 }
 }
 return result;
 }
 })()
 };
 
 | 
    上面的代码在IE7(也许IE8也是)下有个问题,就是如果传入一个来自其他 window 对象下的对象时,不可枚举的属性也会获取到。
    ECMAScript 5中第二E个枚举属性的函数是Object.getOwnPropertyNames(),它和Ojbect.keys()似,只是它返回对象的所有自有属性的名称,而不仅仅是可枚举的属性。在ECMAScript 3中是无法实现的类似的函数的,因为ECMAScript 3中没有提供任何方法来获取对象不可枚举的属性。
Object.getOwnPropertyNames()方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。
语法
Object.getOwnPropertyNames(obj)
参数
obj
    一个对象,其自身的可枚举和不可枚举属性的名称被返回。
返回值
在给定对象上找到的自身属性对应的字符串数组。
描述
Object.getOwnPropertyNames() 返回一个数组,该数组对元素是 obj自身拥有的枚举或不可枚举属性名称字符串。
数组中枚举属性的顺序与通过 for…in 循环(或 Object.keys)迭代该对象属性时一致。数组中不可枚举属性的顺序未定义。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | var arr = ["a", "b", "c"];console.log(Object.getOwnPropertyNames(arr).sort());
 
 
 var obj = { 0: "a", 1: "b", 2: "c"};
 console.log(Object.getOwnPropertyNames(obj).sort());
 
 
 Object.getOwnPropertyNames(obj).forEach(function(val, idx, array) {
 console.log(val + " -> " + obj[val]);
 });
 
 
 
 
 
 | 
    如果你只要获取到可枚举属性,查看Object.keys或用for…in循环(还会获取到原型链上的可枚举属性,不过可以使用hasOwnProperty()方法过滤掉)。getOwnPropertyNames()并不会获取到原型链上的属性。
如下:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | function ParentClass() {}ParentClass.prototype.inheritedMethod = function() {};
 
 function ChildClass() {
 this.prop = 5;
 this.method = function() {};
 }
 
 ChildClass.prototype = new ParentClass;
 ChildClass.prototype.prototypeMethod = function() {};
 
 console.log(
 Object.getOwnPropertyNames(
 new ChildClass()
 )
 );
 
 | 
愿你的坚持终有收获。
JavaScript中keys()和getOwnPropertyNames()详解。