12

Chromeデベロッパーツールのコンソールから次のトレースを取得しました。

> a = [1]
[1]
> b = [2, a]
[2, Array[1]]
> a.push(b)
2
> a.toString()
"1,2,"

toString()オブジェクトグラフの再帰部分をインテリジェントにスキップしたようです。これはどこかに文書化されている標準的な動作ですか?

4

1 に答える 1

6

[ECMA-262: 15.4.4.2]: Array.prototype.toString ( )

toStringメソッドが呼び出されると、次の手順が実行されます。

  1. array値を呼び出した結果にしToObjectましょうthis
  2. with引数の内部メソッドをfunc呼び出した結果とします。[[Get]]array"join"
  3. の場合IsCallable(func)falsefunc標準の組み込みメソッドObject.prototype.toString(15.2.4.2)とします。
  4. 値として提供する[[Call]]内部メソッドと空の引数リストを呼び出した結果を返します。funcarraythis

このtoString関数は意図的に汎用的です。そのthis値がArrayオブジェクトである必要はありません。したがって、メソッドとして使用するために他の種類のオブジェクトに転送できます。toString関数をホストオブジェクトに正常に適用できるかどうかは、実装によって異なります。

これはすべて、基本的に、結果がへの呼び出しであることを意味しますArray.prototype.join()。これはで定義されて15.4.4.5おり、再帰検出を義務付けていません。

[ECMA-262: 15.4.4.5]: Array.prototype.join (separator)

配列の要素はStringsに変換され、次にこれらStringのsが連結され、区切り文字の出現によって分離されます。区切り文字が指定されていない場合は、1つのコンマが区切り文字として使用されます。

joinメソッドは1つの引数、を取りseparator、次の手順を実行します。

  1. 引数として値を渡してO呼び出した結果とします。ToObjectthis
  2. with引数の内部メソッドをlenVal呼び出した結果とします。[[Get]]O"length"
  3. なりましょlenToUint32(lenVal).
  4. の場合separatorundefinedseparator1文字としString ","ます。
  5. なりましょsepToString(separator)
  6. の場合、空のを返しlenます。zeroString
  7. with引数の内部メソッドをelement0呼び出した結果とします。[[Get]]O"0"
  8. element0isundefinedまたはnull、の場合はR、空にしStringます; それ以外の場合は、にしましょRToString(element0)
  9. 1にしましょうk
  10. 繰り返しますが、k<len
    1. とを連結して生成される値とSします。StringRsep
    2. with引数の内部メソッドをelement呼び出した結果とします。[[Get]]OToString(k)
    3. elementundefinedまたはの場合nullnext空になりStringます; それ以外の場合は、としnextますToString(element)
    4. とを連結して生成される値とRします。StringSnext
    5. 1ずつ増やしkます。
  11. 戻りRます。

メソッドのlengthプロパティjoinは1です。

このjoin関数は意図的に汎用的です。そのthis値がArrayオブジェクトである必要はありません。したがって、メソッドとして使用するために他の種類のオブジェクトに転送することができます。join関数をホストオブジェクトに正常に適用できるかどうかは、実装によって異なります。

それで、それは標準的に保証された振る舞いですか?いいえ。

于 2012-12-11T18:23:48.340 に答える