SitePoint Sponsor

User Tag List

Results 1 to 10 of 10
  1. #1
    SitePoint Enthusiast szigeti's Avatar
    Join Date
    May 2005
    Location
    Hungary
    Posts
    70
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Question How to omit methods from for..in

    I have this extension to the Array object:
    Code:
    Array.prototype.contains = function(value) {
    	for (var i = 0, ii = this.length; i < ii; i++)
    	{
    		if (this[i] === value) return true;
    	}
    	return false;
    }
    When I want to loop through an Array with a for..in construct, I will encounter the "contains" method, as it is a property of every Array.

    To remedy this unwanted phenomena, I need to check if the current Array value is a function, and if it is, I have to skip to the next value. But what if I have some functions in the Array which I want to deal with in the loop?

    Is there an easy and elegant way for omitting prototyped user methods from for..in loops?
    Eat healthy,
    Exercise daily,
    Die anyway.

  2. #2
    SitePoint Guru
    Join Date
    Apr 2006
    Posts
    802
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    There is nothing 'elegant' about using a for- in expression on an integer indexed array. That's why they have indexes.

    To loop through any object and skip inherited (from a prototype) properties, test each property with the object's hasOwnProperty method:

    Code:
    var str='';
    for(var p in obj){
          if(obj.hasOwnProperty(p))  str+=p+', ';
    }
    alert(str)

  3. #3
    SitePoint Wizard Pepejeria's Avatar
    Join Date
    Jan 2005
    Location
    Too far up north
    Posts
    1,566
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    hasOwnProperty is broken in Safari.

    Question would be why you would loop an Array using for.. in loop. Use objects instead.

  4. #4
    SitePoint Enthusiast szigeti's Avatar
    Join Date
    May 2005
    Location
    Hungary
    Posts
    70
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by mrhoo View Post
    There is nothing 'elegant' about using a for- in expression on an integer indexed array. That's why they have indexes.
    I never said anything about integer indexed arrays. I wanted to loop through a collection of elements gathered by a getElementByClassName method.
    Eat healthy,
    Exercise daily,
    Die anyway.

  5. #5
    SitePoint Enthusiast szigeti's Avatar
    Join Date
    May 2005
    Location
    Hungary
    Posts
    70
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Pepejeria View Post
    hasOwnProperty is broken in Safari.

    Question would be why you would loop an Array using for.. in loop. Use objects instead.
    I want to loop through the result of a getElementsByClass method.

    Since the document.getElementsByTagName method returns an array, it would be logical to build the getElementsByClass the similar way.

    I have created an alternate version of the said method which returns an object instead of an array, but I found that my user defined method still shows up in the for..in results.

    There is a solution however which is neither elegant nor comfortable, but works with arrays and objects:
    Code:
    for (var i in c) {
      if (!(i in Object.prototype)) {
        // do stuff
      }
    }
    ...but I would prefer something like setting a flag in the prototype definition, that would automagically omit that property from presenting itself inside a for..in statement, the same way it leaves out the native coded methods.
    Eat healthy,
    Exercise daily,
    Die anyway.

  6. #6
    JavaScript Guru (Big Ego) Arielladog's Avatar
    Join Date
    Jul 1999
    Location
    SC, USA
    Posts
    390
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I am still confused as to why you are using a for...in to loop through an array, but, rather than:

    Code:
    for (var i in c) {
      if (!(i in Object.prototype)) {
        // do stuff
      }
    }
    You could do:

    Code:
    for (var i in c) {
      var cur = c.constructor.prototype;
      var found = false;
      while(typeof cur != "undefined") {
        if(typeof cur[i] != "undefined") {
          found = true;
          break;
        }
        cur = cur.constructor.prototype;
      }
      if (!found) {
        // do stuff
      }
    }
    Which I would assume is essentially what .hasOwnProperty should do.

    -Ryan

  7. #7
    SitePoint Enthusiast szigeti's Avatar
    Join Date
    May 2005
    Location
    Hungary
    Posts
    70
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally I thought there should be a way to mark an object property as non-enumerable, so it would be automatically omitted from appearing in a for..in.

    I wanted to learn the name of that "magic method" or property. I could have imagined that if I define a method something like this:
    Code:
    Object.prototype.myFunc = function () {
    this.enumerable = false;// nb does not work!
    // rest of the method
    }
    , it would do the trick.

    Unfortunately it turned out that a user-defined method cannot be flagged as non-enumerable, so I would have to use other, less comfortable methods anyway.

    As for your solution, my only complaint would be that it is more verbose than mine.
    Eat healthy,
    Exercise daily,
    Die anyway.

  8. #8
    JavaScript Guru (Big Ego) Arielladog's Avatar
    Join Date
    Jul 1999
    Location
    SC, USA
    Posts
    390
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You can take a look at this: http://developer.mozilla.org/en/docs...tyIsEnumerable though I don't think there's a way to change it.

    -Ryan

  9. #9
    CSS & JS/DOM Adept bronze trophy
    Join Date
    Mar 2005
    Location
    USA
    Posts
    5,482
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by szigeti View Post
    Since the document.getElementsByTagName method returns an array, it would be logical to build the getElementsByClass the similar way.
    Actually, it returns a NodeList, not an array. A NodeList acts like an array, except it doesn't have Array methods.

    You may find this interesting as well: Firefox 3 is going to have support for getElementsByClassName.
    We miss you, Dan Schulz.
    Learn CSS. | X/HTML Validator | CSS validator
    Dynamic Site Solutions
    Code for Firefox, Chrome, Safari, & Opera, then add fixes for IE, not vice versa.

  10. #10
    SitePoint Enthusiast szigeti's Avatar
    Join Date
    May 2005
    Location
    Hungary
    Posts
    70
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Kravvitz View Post
    Thanks, I knew that. That is why I named my method just "getElementsByClass".
    Eat healthy,
    Exercise daily,
    Die anyway.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •