2

I have extended Array prototype:

if(typeof Array.prototype.filter === 'undefined') Array.prototype.filter = function(fun /*, thisp*/){
  var len = this.length;
  if(typeof fun != "function") throw new TypeError();

  var res = [], thisp = arguments[1];

  for(var i=0;i<len;i++){
    if(i in this){
      var val = this[i]; // in case fun mutates this
      if(fun.call(thisp, val, i, this)) res.push(val);
    }
  }

  return res;
};

For example I have created array:

var A = [ 1, 2, 3, 4, 5 ];

Then I added extra properties to it, that I will use:

A.creator = 'Rustam';
A.created = new Date();

If I will use for-in loop, and browser has not built-in support for Array.filter, it will go through A.filter.

I know this way:

for(var p in A) {
  if (!A.hasOwnProperty(p)) continue
  console.log(p)
};

Is there a way to make A.filter hidden in for-in without using hasOwnProperty?


UPDATE to answer. Browser support:

  • IE9+
  • FF4+
  • Chrome
  • Opera 11.6+
  • Safari 5+
Rustam
  • 1,875
  • 2
  • 16
  • 33
  • I don't understand the question. How do you mean hidden? And on a point of clarity, when you append named properties to your array, it becomes an object - it is no longer an array. – Mitya Jul 31 '12 at 11:51
  • @Utkanos Try to do this with empty object and get length from it. This is not object. jQuery selectors built on arrays with extra properties. – Rustam Jul 31 '12 at 11:54
  • @Rustam - jQuery returns objects, not arrays. Try it - `$('*') instanceof Array` (false). They are array-*like* objects - not actually arrays. – Mitya Jul 31 '12 at 12:07
  • @Utkanos try to create an empty object {} and then use it like array: A[1] = 5; A[2] = 7; then try to get .length. You will not get it. jQuery uses base prototype of Array. – Rustam Jul 31 '12 at 12:11
  • @Utkanos What does this question have to do with jQuery? – Rob W Jul 31 '12 at 12:12
  • If I understand your question correctly, you want to 'extend' the native `for in` language construct to internally use `Array.prototype.filter` instead of having to explicitly call `hasOwnProperty()`, is that right? – chrisfrancis27 Jul 31 '12 at 12:19
  • related: http://stackoverflow.com/questions/5940837/javascript-for-in-and-built-in-properties – Felix Kling Jul 31 '12 at 12:19
  • @Chris Francis No, I want to extend Array. – Rustam Jul 31 '12 at 12:24
  • @Rustam Then you should loop using `for(var i=0; i – Rob W Jul 31 '12 at 12:25
  • @Rob W No, I need extended Array with properties. Array for length and numeric values. Properties for working with data - is is very useful. For-in is used by another programmer to get data and he don't want to use hasOwnProperty in for-in loop. But because this will not work in IE8, I can not extend Array. – Rustam Jul 31 '12 at 12:31
  • 1
    @Rustam I understand that you want to extend `Array.prototype`. My previous comment was pointing to the fact that `for(.. in ..)` loops are considered bad practice for arrays. See also: http://stackoverflow.com/questions/500504/javascript-for-in-with-arrays. – Rob W Jul 31 '12 at 12:33
  • @Rustam - do you recall your own comment? You mentioned jQuery, not me. – Mitya Jul 31 '12 at 12:34
  • @Utkanos This was Rob W question, not my. – Rustam Jul 31 '12 at 12:35

1 Answers1

6

To define a property which does not show up in loops, use Object.defineProperty:

Object.defineProperty(Array.prototype, 'filter', {value:'XYZ'});

This extends Array.prototype with a property called filter with default property descriptors, including enumerable: false, which causes the property to not show up in for( .. in ..) loops.

References

PS: Will not work on older browsers I don't have the browser compatibility matrix for this API.

Community
  • 1
  • 1
Ashwin Prabhu
  • 9,285
  • 5
  • 49
  • 82