Javascript custom Array.prototype interfering with for-in loops

匿名 (未验证) 提交于 2019-12-03 09:02:45

问题:

I was attempting to extend Javascript's Object type with a function that retrieves all of the property names that are part of that object (basically what PHP's array_keys() function does to associative arrays).

Object.prototype.keys = function() {     var a = [];     for (var property in this) {         a.push(property);     }     return a; };  var a = {a:1,b:2,c:3,d:4}; alert(a.toSource());  var b = a.keys(); alert(b.toSource()); 

When the variable b was alerted, I was expecting to see ["a","b","c","d"], instead I'm seeing ["a","b","c","d","keys"].

It appears the for-in loop is including the prototyped keys() functions.

Is it possible to avoid this behaviour whilst still prototying, or should I just avoid prototyping all together?

回答1:

Ahh the joys of extending the built-ins. for..in checks up the entire prototype chain of the object being iterated.

What you need (and I believe this is de-facto now) is a check with hasOwnProperty in your loop:

for (var property in this) {     if (this.hasOwnProperty(property)) {         a.push(property);     } } 

hasOwnProperty ensures that you only get properties that are directly defined on your object (i.e. not up the prototype chain).



回答2:

For most situations, you should avoid extending the native Object.prototype. When you extend it, ALL objects receive those new properties.

Looping over an object properties is a really common task, and as you noted, you were experiencing an unexpected behavior.

I have not seen many people who always use the hasOwnProperty function in their code, I would say that under "controlled environments", maybe being a solo developer working on a project, you could manage those issues, but when the things get bigger, and you have more developers involved, this can cause a lot of problems.

What about making a static function on Object?

Object.keys = function(obj) {   var a = [];   for (var property in obj) {     if (obj.hasOwnProperty(property)) {       a.push(property);     }   }   return a; };  var a = {a:1,b:2,c:3,d:4}; alert(a.toSource());  var b = Object.keys(a); alert(b.toSource()); 


回答3:

This also works:

var items = [     {         id: 1, name: 'Item 1'     },     {         id: 2, name: 'Item 2'     },     {         id: 3, name: 'Item 3'     } ]; items.forEach(function(item, index) {     console.log(item); }); 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!