我们应该在迭代对象的键时使用hasOwnProperty()
,因为Object.prototype
可能被污染,通过原型继承,也会污染所有对象的键。
因此,如果我不污染Object.prototype
,我应该可以跳过hasOwnProperty()
,这会减慢for-in loops的速度。它还可以使代码更简单。
想法:首先检查Object.prototype
是否未被污染,然后不要使用hasOwnProperty()
。
通过以下功能检查Object.prototype
是否未被污染。我将在我的代码中的一个战略位置调用它,这在脚本执行期间偶尔执行(就像我将要处理一堆数据之前)。如果对Object.prototype
:
/* jshint -W089 */ // http://jslinterrors.com/the-body-of-a-for-in-should-be-wrapped-in-an-if-statement/
var checkObjectPrototypeNotAugmented = function() {
/* jshint unused:false */ // Because key is considered unused
// Check if there is any enumerable property on Object.prototype:
for(var key in Object.prototype) {
throw new Error("Object.prototype has been augmented with keys: " + Object.prototype.keys());
}
};
注意:我发出了/* jshint -W089 */
评论,以便jshint不会complain about missing hasOwnProperty()
。
问题:这可以吗?还有什么我应该小心的吗?或者我可以改进?
现在有些基准测试:
以下是3个jsPerf基准测试,显示具有不同属性数的对象的增益:
注意:每次要迭代对象的属性时,都会执行Object.prototype
检查。在实际情况下,测试只需要执行一次:加载整个页面时(然后不时地确保没有脚本无意中被修改Object.prototype
)。因此,在实际情况下,您将获得“参考”测试的性能。但这表明,即使总是进行测试,它也会保持更快。
有趣的结果:
hasOwnProperty()
可以提供相同的速度,也可以更快,具体取决于浏览器Object.protoype
在某些浏览器中比hasOwnProperty()
更快! (但我不建议总是这样检查Object.prototype
) 相关:我们还看到,对于大型对象,在某些浏览器中使用Object.keys()
可能会更快,但对于小对象来说,它也可能更慢。但是使用Object.keys()
会强制您只支持浏览器> = IE 9,或者在IE< = 8中使用polyfill扩充Object.prototype
。因此,对于旧的浏览器兼容性,您必须选择Object.keys()
或checkObjectPrototypeNotAugmented()
。