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 "~"
).
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. –
Krok "~" został usunięty przez rev 32. – Knu
"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