0

The koan is below. In my lessons, I've never seen the word "Array" just stuck into code like that. Any examples elsewhere that I can study?

it("should know properties that are functions act like methods", function ()
{
  var meglomaniac = {
    mastermind : "Brain",
    henchman: "Pinky",
    battleCry: function (noOfBrains)
    {
      return "They are " + this.henchman + " and the" +
      Array(noOfBrains + 1).join(" " + this.mastermind);
    }
};

var battleCry = meglomaniac.battleCry(4);
expect(FILL_ME_IN).toMatch(battleCry);
});

It should know properties that are functions act like methods. It is damaging your karma.

Expected 'Fill this value in' to match 'They are Pinky and the Brain Brain Brain Brain'.

dwilbank
  • 2,470
  • 2
  • 26
  • 37
  • 1
    [ECMAScript 15.4.1, The Array Constructor Called as a Function](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.1): "When `Array` is called as a function rather than as a constructor, it creates and initialises a new Array object. Thus the function call `Array(...)` is equivalent to the object creation expression `new Array(...)` with the same arguments." – apsillers Sep 04 '13 at 19:03
  • See also point #5 in [this answer](http://stackoverflow.com/a/9033306/1233508). It's a little muddied by the `NaN` conversions, which are irrelevant in this case, but it explains the trick and provides links to the standard where this behaviour is defined. – DCoder Sep 04 '13 at 19:04
  • Then I have Array(5).join(" " + "Brain"); and this still doesn't output anything I would recognize... – dwilbank Sep 04 '13 at 19:06
  • OK - reading point #5. Looks promising... – dwilbank Sep 04 '13 at 19:07
  • it's just a cheap string repeater... – dandavis Sep 04 '13 at 19:08
  • and a completely new one to me, apparently - thanks – dwilbank Sep 04 '13 at 19:09
  • Check out [String repeat in javascript](http://stackoverflow.com/questions/202605/repeat-string-javascript) maybe – Bergi Sep 04 '13 at 19:24

2 Answers2

4

So, Array(noOfBrains + 1) creates a new array of length five (well, given that noOfBrains is passed in as 4), in which every element is undefined:

[undefined, undefined, undefined, undefined, undefined]

Then, the join operation takes a string (" Brain"), and places a copy of it between each element of the array. (A more common use of join is something like array.join(", ") which comma-separates an array)

So we essentially have:

undefined + " Brain" + undefined + " Brain" + undefined + " Brain"+ undefined + " Brain" + undefined

Which becomes " Brain Brain Brain Brain", since the undefined's are ignored by join.

Retsam
  • 30,909
  • 11
  • 68
  • 90
  • 1
    Actually the point is that there are no items at all, but the length is 5. Only when you're accessing them they will yield `undefined`, but it's a *sparse array* without elements. – Bergi Sep 04 '13 at 19:20
  • This is some crazy stuff to put in a Koan. Thanks. – dwilbank Sep 04 '13 at 19:24
  • @Bergi Ah; I wasn't aware that there was a distinction between "each element is undefined" and "the array has no elements". Seems like a bit of a philosophical point, but I'll take your word for it. – Retsam Sep 05 '13 at 18:47
  • This koan blew my head up too. I was expecting Brain Brain Brain Brain Brain - the join threw me :-@ – Jonathan Apr 20 '16 at 15:12
1

According to ECMAScript 15.4.1, Array(...) acts just like new Array(...):

When Array is called as a function rather than as a constructor, it creates and initialises a new Array object. Thus the function call Array(...) is equivalent to the object creation expression new Array(...) with the same arguments.

According to ES 15.4.2.2, the single-argument form new Array(len) creates an empty array with the length property set to the value of the argument. So, Array(noOfBrains + 1) creates an empty array of size noOfBrains + 1.

According to ES 15.4.4.5, .join(separator) loops over the array for the value of the array's length (step 10). It builds a string by concatenating values from the array, joined by the separator value passed as an argument to join. According to step 8 and step 10.c, undefined array values are rendered as the empty string by .join.

Since the array you just initialized is empty, all of its values are undefined. Therefore, .join joins a list of the empty strings with the separator string "Brain".

apsillers
  • 112,806
  • 17
  • 235
  • 239