在javascript的内置函数中进行循环检测

bil*_*.cn 12 javascript

我从Chrome开发人员工具的控制台获得了以下跟踪:

> a = [1]
[1]
> b = [2, a]
[2, Array[1]]
> a.push(b)
2
> a.toString()
"1,2,"
Run Code Online (Sandbox Code Playgroud)

似乎toString()智能地跳过了对象图的递归部分.这是在某处记录的标准行为吗?

Lig*_*ica 6

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

toString调用该方法时,将执行以下步骤:

  1. 我们array要呼吁的结果ToObject的this值.
  2. 让我们func调用with参数的[[Get]]内部方法.array"join"
  3. 如果IsCallable(func)是false,那么让我们func成为标准的内置方法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然后连接这些元素,由分隔符的出现分隔.如果未提供分隔符,则使用单个逗号作为分隔符.

join方法接受一个参数separator,并执行以下步骤:

  1. 让我们O调用ToObject传递this值作为参数的结果.
  2. 让我们lenVal调用with参数的[[Get]]内部方法.O"length"
  3. 让len是ToUint32(lenVal).
  4. 如果separator是undefined,那separator就是单个字符String ",".
  5. 我们sep是ToString(separator).
  6. 如果len是zero,返回空String.
  7. 让我们element0调用with参数的[[Get]]内部方法.O"0"
  8. 如果element0是undefined或null,让R是空的String; 否则,我们R是ToString(element0).
  9. 让我们k1.
  10. 重复,而k<len
    1. 我们S是String通过连接产生的价值R和sep.
    2. 让我们element调用with参数的[[Get]]内部方法.OToString(k)
    3. 如果element是undefined或null,让我们next空虚String; 否则,我们next是ToString(element).
    4. 让我们通过连接和生成R一个String值.Snext
    5. 增加k1.
  11. 返回R.

该方法的length属性join是1.

注意该join功能是有意通用的; 它不要求它的this值是一个Array对象.因此,它可以转移到其他种类的对象以用作方法.join函数是否可以成功应用于宿主对象取决于实现.

那么,这是一种标准保证的行为吗?没有.