0

I've been wondering whether I can eliminate the duplicate line in the function below, but have not be able to arrive at a non-recursive solution.

Just out of curiosity, is there a way to eliminate the duplicate line, but without recursion?

function accumulateOverProtos(obj, propName) {
  var accumulator = []                                                                                                                                                                       
  if (obj.hasOwnProperty(propName)) accumulator.push(obj[propName])                                                                                                                          
  while (obj = Object.getPrototypeOf(obj)) {                                                                                                                                                 
    if (obj.hasOwnProperty(propName)) accumulator.push(obj[propName])                                                                                                                        
  }                                                                                                                                                                                          
  return accumulator                                                                                                                                      
}

Also, could anyone point me to some reading on this sort of thing? What is this issue/problem called?

Dmitry Minkovsky
  • 36,185
  • 26
  • 116
  • 160
  • 1
    ?? I don't see any recursion in that code. – Pointy Jan 20 '14 at 17:01
  • There is no recursion, but I've arrived at a recursive solution without the redundancy. Just didn't post it. – Dmitry Minkovsky Jan 20 '14 at 17:01
  • You're looking for the `do while` loop. – SLaks Jan 20 '14 at 17:02
  • Thanks SLaks. This, of course, lets you make the assignment first. – Dmitry Minkovsky Jan 20 '14 at 17:04
  • Your code is missing all the semicolons. Technically you can do this. Practically you shouldn't. – Tomalak Jan 20 '14 at 17:04
  • @Tomalak I am enjoying learning the syntactic details of JS by running in to problems of ASI. That said, half a year of with JS, I've only run into ASI-related issues once. That issue was calling a closure like (function(){}()) without a ; on the preceding line. And, now I know! – Dmitry Minkovsky Jan 20 '14 at 17:08
  • @Tomalak: so, specifically, I also ask, why not promote learning instead of promoting non-learning? It seems to me there's nothing practical about being in the dark. – Dmitry Minkovsky Jan 20 '14 at 17:10
  • I understand that most of the time it's not a problem. Still, *explicit is better than implicit* - and it's against every established convention and static analyzers are not happy with it. It's avoidable source code cleverness (is smartypantsness a word?) without any real benefit. – Tomalak Jan 20 '14 at 17:11
  • @Tomalak, I see. Thanks for the answer. Static analyzers aside, isn't the syntax of JS what provides the explicitness? I just don't understand what's _not explicit_? As far as I've experienced, there is definitively no non-explicitness in programming languages. They are definitively explicit. For me, personally, ; are a huge visual blight and not having them makes code much easier to read. For me, this is not cleverness w/o real benefit. But alas, we digress. Thanks for the answer :D. – Dmitry Minkovsky Jan 20 '14 at 17:14
  • The same thing that goes for dangling `if` statments. They are explicit... to a parser. They're mostly explicit to the experienced developer. They are ambiguous to the untrained eye. They are a source of easy-to-avoid bugs. They make you *think* while reading the source code. And that's something that should be avoided. – Tomalak Jan 20 '14 at 17:18
  • @Tomalak: is this the correct page to read about dangling `if` statements? http://en.wikipedia.org/wiki/Dangling_else Or is dangling `if` a separate issue? – Dmitry Minkovsky Jan 20 '14 at 17:22
  • @dimadima Yes, that's what I meant. It works, but it's still a code smell. – Tomalak Jan 20 '14 at 17:23

2 Answers2

3

A perfect use case for do...while.

function accumulateOverProtos(obj, propName) {
    var accumulator = [];

    do {
        if (obj.hasOwnProperty(propName)) accumulator.push(obj[propName]);
    } while (obj = Object.getPrototypeOf(obj));

    return accumulator;
}
James Montagne
  • 77,516
  • 14
  • 110
  • 130
1

You could just use a simple for loop:

function accumulateOverProtos(obj, propName) {
  var accumulator = [];                                                         
  for (; obj; obj = Object.getPrototypeOf(obj))
    if (obj.hasOwnProperty(propName)) accumulator.push(obj[propName]);
  return accumulator;
}
Pointy
  • 405,095
  • 59
  • 585
  • 614
  • I've been wondering about usage of the `for` loop—wherein there's no initialization expression—for a long time. This is pretty much a more performant `do`/`while` ("more performant" just because this appears to be the case on jsperf). – Dmitry Minkovsky Jan 20 '14 at 17:40
  • 1
    @dimadima I doubt there's a performance difference. It's just a matter of preference or style. – Pointy Jan 20 '14 at 17:40