基本描述
语法
Object.keys(obj)
参数
- obj 要返回自身可枚举属性的对象
返回值
一个表示obj自身可枚举属性的字符串数组
polyfill
要获取一个对象可枚举的属性,可以使用for in
,要判断是否是自身的属性,可以使用hasOwnProperty
。这样核心功能的原理就介绍完了。
下面代码依然出自MDN
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;
}
})();
};
你可能会好奇,为什么用hasOwnProperty.call(obj, prop)
,用obj.hasOwnProperty(prop)
不行吗?其实对于绝大部分情况下没问题,但是如果是Object.create(null)
创建出来的对象,它是无法访问到Object.prototype上的方法的,换句话说在这种情况下使用obj.hasOwnProperty
会报错。
上面代码的绝大部分是处理某些浏览器的bug的,在underscore.js有类似代码,作者加了一行这样的注释:
Keys in IE < 9 that won't be iterated by
for key in ...
and thus missed.
都懂的。
这里的立即执行的匿名函数表达式、闭包、模拟静态私有变量就不说了,都是日常了。
一个相关的方法是Object.getOwnPropertyNames()
,他返回的是一个对象自身属性的属性名(包括不可枚举属性),这个不可枚举就比较尴尬了,我没有办法通过for in
来获取属性名,所以这个方法不能被polyfill。
以上