How do arguments objects print?

# Mark S. Miller (17 years ago)

In the 23feb09 draft, arguments objects have a [[Class]] of "Object" and inherit their toString property from Array.prototype. Array.prototype.toString in effect simply does "return this.join();". However, Array.prototype.toString is not generic (it insists that its this have [[Class]] "Array") even though Array.prototype.join() is generic. Altogether, by the 23feb09 draft, attempting to print an arguments object must result in a throw. I doubt this is what anyone intends. Could we simply make Array.prototype.toString generic, so that the it works when inherited?

Btw, I notice on Safari that the [[Class]] of an arguments object is "Arguments". Given how weird the arguments object is, if it is not too late, I think Safari's special [[Class]] value would be a good idea.

# Brendan Eich (17 years ago)

On Feb 27, 2009, at 11:59 PM, Mark S. Miller wrote:

In the 23feb09 draft, arguments objects have a [[Class]] of "Object"
and inherit their toString property from Array.prototype.
Array.prototype.toString in effect simply does "return
this.join();". However, Array.prototype.toString is not generic (it
insists that its this have [[Class]] "Array") even though
Array.prototype.join() is generic. Altogether, by the 23feb09 draft,
attempting to print an arguments object must result in a throw. I
doubt this is what anyone intends. Could we simply make
Array.prototype.toString generic, so that the it works when inherited?

Compatibility means returning "[object Object]" from (function f() {return arguments;})().toString(). At least for browsers other than
Safari. I don't know of any web content that counts on this, but I
haven't looked and it's a big web ;-).

Btw, I notice on Safari that the [[Class]] of an arguments object is
"Arguments". Given how weird the arguments object is, if it is not
too late, I think Safari's special [[Class]] value would be a good
idea.

That's a better idea than what ES1-3 say, for sure. I wonder whether
that goes back to the kjs dawn of time. Cc'ing Maciej.

We could try this out during implementation of 3.1, before finalizing
the standard. Is it better than making the delegated
Array.prototype.toString generic, though?

# Allen Wirfs-Brock (17 years ago)

Good, this thread caused me to identify another bug, step 4 of 10.5 (create the arguments Object) currently sets the [[Constructor]] (???) internal property to Object. It should be using [[DefineOwnProperty]] to set the "constructor" property. This is necessary because Array.prototype specifically defines its "constructor" property to be Array so it needs to be over-ridden.

I think we should try both of the suggestions in the ES3.1 candidate. The [[Class]] of an arguments object should be "Arguments" and Array.prototype.printString should be made generic.

However, that opens up two questions: exactly how to make Array.prototype's printString generic and does arguments need its own over-ride to printString. I think, a reasonable answer to the first, is to simply define Array.prototype's printString to be generic and say it is as if it did this.join(). For the second, I think arguments needs an over-ride that results in "[object Arguments]" unless somebody wants to seriously argue that it should have the this.join() behavior.

We (Mark?) should also carefully review the definition of Array.prototype's methods to make sure there isn't any other unnecessary non-generic behavior specified.

As a side note, if user code wanted to "reuse" Array.prototype the way we are for the arguments object I would think the preferred way would be to create a new prototype that inherits from Array.prototype such as: MyArrayLikeConstructor.prototype = Object.create(Array.prototype, { constructor: {value: MyArrayLikeConstructor, writable: true,configurable: true}, etc...}}; I'm not seriously suggesting (extra spec. work, unexplored implications of reifying such a prototype) that we do the same for arguments objects but it does feel like that would be a better design.

# Allen Wirfs-Brock (17 years ago)

Here is what I propose for Array.prototype.toString (minus the formatting):

15.4.4.2 Array.prototype.toString ( ) When the toString method is called, the following steps are taken:

  1. Let array be the result of calling ToObject on the this value.
  2. Let func be the result of calling the [[Get]] internal method of array with argument "join".
  3. If IsCallable(func) is false, then let func be the standard built-in method Object.prototype.toString (15.2.4.2).
  4. Return the result of calling the [[Call]] internal method of func providing array as the this value and an empty arguments list. NOTE The toString function is intentionally generic; it does not require that its this value be an Array object. Therefore it can be transferred to other kinds of objects for use as a method. Whether the toString function can be applied successfully to a host object is implementation-dependent.