2012-10-31 14 views
6

ja czytania w zanurzeniu na ES6, i zauważyli to oznaczenie w punkcie Object.prototype.toString:dostępu [[NativeBrand]]/[[Klasa]] w ES6 (ECMAScript 6)

Historycznie, funkcja był czasami używany do uzyskania wartości ciągu znaków właściwości wewnętrznej [[Klasa]], która była używana w poprzednich wersjach tej specyfikacji jako znacznik typu nominalnego dla różnych wbudowanych obiektów . Ta definicja toString zachowuje zdolność do użycia go jako wiarygodnego testu dla tych konkretnych rodzajów wbudowanych obiektów , ale nie zapewnia niezawodnego mechanizmu testowania typu dla innych typów wbudowanych lub zdefiniowanych programów.

Od czytania this thread na es-dyskutować, to brzmi jak [[Class]] jest zastąpiony [[NativeBrand]] w projekcie ES6 tak, że mogą określić go jako non-rozciągliwy (to były przynajmniej Allen Wirfs-Brock's thoughts).

Ciekawy, wpadłem szybki test w Firefoksie i Chrome (z włączoną obsługą JavaScript eksperymentalnej):

Object.prototype.toString.apply(new WeakMap()); 
=> '[object WeakMap]' 

"WeakMap" nie jest jednym z [[NativeBrand]] s określonych w projekcie ES6. Jednak ten test zwrócił "[object WeakMap]" w obu przeglądarkach.

Jestem zdezorientowany. Mam kilka pytań.


1. Czy Chrome i Firefox działają poprawnie?

Z jednego sposobu czytania wersji roboczej wynika, że ​​powinien on powrócić: [object Object] (i wszystko to jest całkiem nowe, więc nie zdziwiłbym się, widząc tę ​​zmianę w przyszłych wersjach tych przeglądarek). Trudno mi jednak zrozumieć intencje tej części projektu, zwłaszcza, że ​​jest kilka miejsc z "???".

Czy ktokolwiek, kto śledził es-dyskutować bardziej żarliwie, posiada wszelkie istotne informacje? A może ktoś, kto lepiej zrozumie wersję roboczą języka?


2. Czy istnieje alternatywa dla Object.prototype.toString?

Z cytowanej powyżej notatki wynika, że ​​brzmi ona tak, jakby Object.prototype.toString została zachowana ze względów starszego typu, tak jakby teraz było coś nowego, co powinno zostać użyte. Zwłaszcza część węzła, która czyta "it does not provide a reliable type testing mechanism for other kinds of built-in ... objects". Czy to oznacza, że ​​przyszłe wbudowane nie mogą być testowane tą metodą?

Wykorzystajmy konkretny przykład.

Jeśli chcę, aby zapewnić obiekt Otrzymałem z nieznanego źródła jest String obiektu (rzeczywiste skonstruowane String przedmiot, a nie prymitywne string), mogę zrobić:

if (Object.prototype.toString.apply(unknownObject) != '[object String]') 
    throw new TypeError('String object expected.'); 

To pozwala mi znać jeśli jest to obiekt o dowolnej konstrukcji, bez względu na to, w jakiej ramce został skonstruowany.

Moje pytanie brzmi, czy powinno to być podejście, które podchodzę do ES6? Czy istnieje alternatywa? Coś takiego jak Object.getNativeBrandOf?


3. Od [[NativeBrand]] Wygląda na to, że nie będzie to w przyszłości typów obiektów, w jaki sposób jeden test dla tych obiektów?

Czy to zadziała?

if (Object.prototype.toString.apply(unknownObject) != '[object Symbol]') 
    throw new TypeError('Symbol expected.'); 

... zakładając Symbol jest ewentualna nazwa Private Names.

Czy powinienem użyć tego?

if (Object.prototype.toString.apply(unknownObject) != '[object WeakMap]') 
    throw new TypeError('WeakMap expected.'); 

... czy coś jeszcze?


Pytam jest obecnie piszę kod, który chcę, aby być w stanie przejść tak łatwo, jak to możliwe, aby ES6 w rok lub dwa, gdy to możliwe. Jeśli istnieje zamiennik dla Object.prototype.toString, mogę go po prostu wrzucić i kontynuować. Dzięki!


Aktualizacja

benvie „s odpowiedź mi z prawidłowym terminem, aby szukać i zrozumieć odpowiedź na moje pytania.

Znalazłem an email from Allen Wirfs-Brock on es-discuss dotyczący tego problemu.

Oto co znalazłem, dla nikogo innego zadawać te same pytania:

1. Do Chrome i Firefox zachowywać się poprawnie?

Tak, dlaczego wyjaśniono poniżej.

2. Czy istnieje alternatywa dla Object.prototype.toString?

Jak jest teraz, nie będzie kilka „alternatywy” w sensie możliwości, ale nie w sensie zamienników.

a.Symbolem @@toStringTag. Jednak rozumiem, że prawdopodobnie nadal powinno się używać Object.prototype.toString. @@toStringTag zapewnia rozszerzenie wyników, które można zwrócić od Object.prototype.toString. Jeśli masz prototyp, do którego chcesz dodać własny ciąg znaków, możesz użyć wartości @@toStringTag, aby ustawić wartość dowolnego ciągu. Object.prototype.toString zwróci tę wartość, z wyjątkiem przypadku, gdy ta wartość jest jednym z wbudowanych w ES5, w którym to przypadku znacznik łańcucha będzie poprzedzony znakiem "~".

b.Używanie prywatnych symboli na obiektach zdefiniowanych przez użytkownika. Przeczytałem jedną wiadomość e-mail promującą to jako najlepszy sposób wykonywania tego samego typu sprawdzania obiektu zdefiniowanego przez użytkownika. Jednak nie widzę, jak to naprawdę rozwiązuje problem, ponieważ nie rozumiem, w jaki sposób może to być rozwiązanie międzymiarowe i nie pozwala na sprawdzenie wbudowanych w ES6.

Więc chociaż istnieją pewne alternatywy, dobrze jest trzymać się Object.prototype.toString teraz i posuwają się do przodu, z jednym zastrzeżeniem:

będziemy pracować, aby upewnić się masz ES5 wbudowane, takie jak String, ale nie będzie to głupie, aby upewnić się, że masz wbudowany ES6, ponieważ można go sfałszować przy pomocy @@toStringTag. Nie jestem pewien, dlaczego tak się dzieje, a może coś mi brakuje, albo może się zmienić w miarę rozwoju specyfikacji.

3. Od wydaje się, że nie będzie zawierać przyszłych typów obiektów, w jaki sposób jeden test dla tych obiektów?

Jak wspomniano powyżej, Object.prototype.toString mogą być nadal używane na ES6 wbudowanych wtyczek, ale to nie jest idiotoodporny, ponieważ może być sfałszowane przez osoby z dostępem do @@toStringTag symbolem. Być może jednak nie powinien istnieć niepoprawny metoda, ponieważ Object.prototype.toString(weakmap) == '[object WeakMap]' nie oznacza, że ​​weakmap instanceof WeakMap (i nie powinno!). Model weakmap mógł pochodzić z innej ramki lub może być utworzonym przez użytkownika obiektem o słabej strukturze. Jedyną rzeczą, którą naprawdę wiesz, jest to, że jest funkcjonalnie równoważny z WeakMap.

Wydaje żebrać na pytanie dlaczego nie można mieć obiekt zdefiniowany przez użytkownika, który zgłosi się funkcjonalnym odpowiednikiem String lub Array (sans prefiksem "~").

+0

odpowiedzią na bardzo ostatniego pytania (o ~, etc.) jest to, że nie ma istniejącego kodu w sieci, które zależy od istniejących Wartości wyników OptoString nie są fałszywe dla istniejących wbudowanych ES5. Chcemy zachować tę gwarancję, ale tylko dla wartości objects/[[Class]], o której O.p.toString wiedział w ES <= 5. –

+0

Krok "~" został usunięty przez rev 32. – Knu

+0

"To pozwala mi wiedzieć, czy unknownObject jest obiektem typu String, bez względu na to, w jakiej ramce został on zbudowany." nie w Operze. – Knu

Odpowiedz

1

To jest obecnie ruchomy cel w specyfikacji ES6. W przypadku istniejącego zestawu obiektów istniejąca mechanika jest utrzymywana z różnych powodów, w tym ze względu na kompatybilność. W najnowszym ES6 specyfikacji, published October 26th można znaleźć kilka wskazówek potencjalnego kierunku przyszłej

15.4.6.2.4ArrayIterator.prototype. @@ toStringTag
Wartość początkowa z @@ Właściwość toStringTag jest wartością ciągu znaków "Array Iterator" .

15.14.5.13Map.prototype. @@ toStringTag
Początkowa wartość @@ własności toStringTag jest wartość ciągu "Mapa".

można znaleźć oryginalną dyskusję, która pochodzi ten in this thread na es-dyskutować

+0

Dzięki, że wskazał mi właściwy kierunek i dał mi termin, którego potrzebowałem. Zaktualizowałem moje pytanie z bardziej kompletną odpowiedzią powyżej, dla potomności. –

Powiązane problemy