Pytanie Wykrywanie pętli we wbudowanych funkcjach javascript


Otrzymałem następujący ślad z konsoli narzędzia programisty Chrome:

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

Wydaje się, że toString() inteligentnie pominięto rekurencyjną część wykresu obiektów. Czy jest to gdzieś udokumentowane standardowe zachowanie?


12
2017-12-11 18:14


pochodzenie


@LightnessRacesinOrbit a.toString() nie ma nic wspólnego z przeglądarkami. Mógł równie dobrze zrobić alert(a.toString()); - Christian
Byłoby fajnie, gdyby zalogował się "1,2, miła próba" - Adam Rackis
@ Chrześcijanin: Hmm? - Lightness Races in Orbit
Pokazuje Chrome [1, Array[2]] i rozwija się praktycznie w nieskończoność jsfiddle.net/j08691/sXURS - j08691
W nodejs widzę [ 1, [ 2, [Circular] ] ] - Shiplu Mokaddim


Odpowiedzi:


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

Kiedy toString Metoda jest wywoływana, podejmowane są następujące kroki:

  1. Pozwolić array być rezultatem dzwonienia ToObject na this wartość.
  2. Pozwolić func być rezultatem dzwonienia do [[Get]] metoda wewnętrzna array z argumentem "join".
  3. Gdyby IsCallable(func) jest false, wtedy pozwolić func być standardową wbudowaną metodą Object.prototype.toString (15.2.4.2).
  4. Zwróć wynik wywołania [[Call]] metoda wewnętrzna func że array jako this wartość i pusta lista argumentów.

UWAGA The toString funkcja jest celowo ogólna; to nie wymaga tego this wartość to an Array obiekt. W związku z tym można go przenieść do innych rodzajów obiektów do wykorzystania jako metoda. Czy toString Funkcja może zostać pomyślnie zastosowana do obiektu hosta zależna od implementacji.

Wszystko to w zasadzie oznacza, że ​​wynikiem jest połączenie Array.prototype.join(), który jest zdefiniowany w 15.4.4.5 i nie nakazuje wykrywania rekurencji:

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

Elementy tablicy są konwertowane na Strings, i te Strings są następnie konkatenowane, oddzielone wystąpieniami separatora. Jeśli nie ma separatora, jako separator używany jest pojedynczy przecinek.

Metoda łączenia przyjmuje jeden argument, separatori wykonuje następujące kroki:

  1. Pozwolić O być rezultatem dzwonienia ToObject przechodząc this wartość jako argument.
  2. Pozwolić lenVal być rezultatem dzwonienia do [[Get]] metoda wewnętrzna O z argumentem "length".
  3. Pozwolić len być ToUint32(lenVal).
  4. Gdyby separator jest undefined, pozwolić separator być pojedynczym znakiem String  ",".
  5. Pozwolić sep być ToString(separator).
  6. Gdyby len jest zero, zwróć puste String.
  7. Pozwolić element0 być rezultatem dzwonienia do [[Get]] metoda wewnętrzna O z argumentem "0".
  8. Gdyby element0 jest undefined lub null, pozwolić R być pustym String; inaczej, Let R być ToString(element0).
  9. Pozwolić k być 1.
  10. Powtarzaj, podczas gdy k < len
    1. Pozwolić S być String wartość wytworzona przez konkatenację R i sep.
    2. Pozwolić element być rezultatem dzwonienia do [[Get]] metoda wewnętrzna O z argumentem ToString(k).
    3. Gdyby element jest undefined lub null, Pozwolić next być pustym String; inaczej, niech next być ToString(element).
    4. Pozwolić R być a String wartość wytworzona przez konkatenację S i next.
    5. Zwiększać k o 1.
  11. Powrót R.

The length własność join metoda to 1.

UWAGA The join funkcja jest celowo ogólna; to nie wymaga tego this wartość to an Array obiekt. W związku z tym można go przenieść na inne rodzaje obiektów do wykorzystania jako metoda. Czy join Funkcja może zostać pomyślnie zastosowana do obiektu hosta zależna od implementacji.

Czy jest to zachowanie gwarantowane przez standard? Nie.


6
2017-12-11 18:23