Jaka jest motywacja do wprowadzenia symboli do ES6?
UPDATE : niedawno pojawił się genialny artykuł z Mozilli . Przeczytaj, jeśli jesteś ciekawy.
Jak zapewne wiecie, planują dodanie nowego symbolu prymitywnego typu w ECMAScript 6 (nie wspominając o innych szalonych rzeczach). Zawsze uważałem, że pojęcie :symbol
W Rubim jest zbędne; zamiast tego możemy łatwo używać zwykłych łańcuchów, tak jak to robimy w JavaScript. A teraz postanawiają tym skomplikować sprawy w JS.
5 answers
Oryginalną motywacją do wprowadzenia symboli do Javascript było włączenie prywatnych właściwości.
Niestety, zostały one poważnie obniżone. Nie są już prywatne, ponieważ można je znaleźć poprzez odbicie, na przykład za pomocąObject.getOwnPropertySymbols
lub proxy.
Są teraz znane jako unikalne symbole, a ich jedynym przeznaczeniem jest unikanie kolizji nazw między właściwościami. Na przykład sam ECMAScript może teraz wprowadzać Hooki rozszerzeń za pomocą pewnych metody, które można umieścić na obiektach (np. aby zdefiniować ich protokół iteracji) bez ryzyka kolizji z nazwami użytkowników.
Czy jest to wystarczająco silna motywacja do dodawania symboli do języka jest dyskusyjna.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-04 05:46:51
Symbole nie gwarantują prawdziwej prywatności, ale mogą być używane do oddzielania publicznych i wewnętrznych właściwości obiektów. Weźmy przykład, gdzie możemy użyć Symbol
do posiadania prywatnych własności.
Weźmy przykład, w którym własność obiektu nie jest prywatna.
var Pet = (function() {
function Pet(type) {
this.type = type;
}
Pet.prototype.getType = function() {
return this.type;
}
return Pet;
}());
var a = new Pet('dog');
console.log(a.getType());//Output: dog
a.type = null;
//Modified outside
console.log(a.getType());//Output: null
Powyżej własność klasy Pet
type
nie jest prywatna. Aby uczynić to prywatnym, musimy stworzyć zamknięcie. Poniższy przykład ilustruje, jak możemy uczynić type
prywatnym za pomocą zamknięcie.
var Pet = (function() {
function Pet(type) {
this.getType = function(){
return type;
};
}
return Pet;
}());
var b = new Pet('dog');
console.log(b.getType());//dog
b.type = null;
//Stays private
console.log(b.getType());//dog
Wada powyższego podejścia: wprowadzamy dodatkowe zamknięcie dla każdej utworzonej instancji Pet
, które może zaszkodzić wydajności.
Teraz przedstawiamy Symbol
. Może to pomóc nam uczynić nieruchomość prywatną bez korzystania z dodatkowych niepotrzebnych zamknięć. Przykład kodu poniżej:
var Pet = (function() {
var typeSymbol = Symbol('type');
function Pet(type) {
this[typeSymbol] = type;
}
Pet.prototype.getType = function(){
return this[typeSymbol];
}
return Pet;
}());
var a = new Pet('dog');
console.log(a.getType());//Output: dog
a.type = null;
//Stays private
console.log(a.getType());//Output: dog
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-19 17:06:49
Symbols
są nowym, specjalnym rodzajem obiektów, które mogą być używane jako unikalna nazwa właściwości w obiektach. Użycie {[3] } zamiast string
pozwala różnym modułom tworzyć właściwości, które nie są ze sobą sprzeczne. Symbols
mogą być również prywatne, tak, że ich właściwości nie mogą być dostępne dla nikogo, kto nie ma już bezpośredniego dostępu do Symbol
.
Symbols
są nowym prymitywnym . Tak jak w number
, string
, i boolean
prymitywy, Symbol
mają funkcję, która może być używane do ich tworzenia. W przeciwieństwie do innych prymitywów, Symbols
nie mają dosłownej składni (np. jak string
mają ''
) - jedynym sposobem ich utworzenia jest użycie konstruktora Symbol
w następujący sposób:
let symbol = Symbol();
W rzeczywistości, Symbol
są tylko nieco innym sposobem dołączania właściwości do obiektu - możesz łatwo dostarczyć dobrze znane Symbols
jako standardowe metody, tak jak Object.prototype.hasOwnProperty
, które pojawiają się we wszystkim, co dziedziczy z Object
.
Oto niektóre z korzyści płynących z Typ prymitywny.
Symbols
mają wbudowaną debuggability
Symbols
można podać opis, który jest tak naprawdę używany do debugowania, aby ułatwić życie podczas logowania ich do konsoli.
Symbols
może być używany jako Object
klucze
Tutaj robi się naprawdę ciekawie. Są mocno splecione z przedmiotami. Symbol
mogą być przypisane jako klucze do obiektów, co oznacza, że można przypisać nieograniczoną liczbę unikalnych Symbol
'S do obiektu i być gwarantuje, że nigdy nie będą one sprzeczne z string
klucze, lub inne unikalne Symbols
.
Symbols
może być używana jako unikalna wartość.
Załóżmy, że masz bibliotekę logowania, która zawiera wiele poziomów logów, takich jak logger.levels.DEBUG
, logger.levels.INFO
, logger.levels.WARN
i tak dalej. W kodzie ES5 należy utworzyć string
s (so logger.levels.DEBUG === 'debug'
) lub number
s (logger.levels.DEBUG === 10
). Obie te wartości nie są idealne, ponieważ te wartości nie są unikalnymi wartościami, ale Symbol
S są! Więc logger.levels
po prostu staje się:
log.levels = {
DEBUG: Symbol('debug'),
INFO: Symbol('info'),
WARN: Symbol('warn'),
};
log(log.levels.DEBUG, 'debug message');
log(log.levels.INFO, 'info message');
Czytaj więcej w tym Wielki artykuł.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-05 06:57:20
Oto Jak to widzę. Symbole zapewniają "dodatkowy poziom prywatności", zapobiegając ujawnianiu kluczy/właściwości obiektu za pomocą niektórych popularnych metod, takich jak Object.keys() i JSON.stringify ().
var age = Symbol(); // declared in another module perhaps?
class Person {
constructor(n,a){
this.name = n;
this[age] = a;
}
introduce(){
console.log(`My name is ${this.name}. I am ${this[age]-10}.`);
}
}
var j = new Person('Jane',45);
j.introduce(); // My name is Jane. I am 35.
console.log(JSON.stringify(j)); // {"name":"Jane"}
console.log(Object.keys(j)); // ["name"]
console.log(j[age]); // 45 (well…only if you know the age in the first place…)
Chociaż dany obiekt sam w sobie, takie właściwości mogą być wystawione przez odbicie, proxy, obiekt.getOwnPropertySymbols () itd., nie ma naturalnych środków, aby uzyskać do nich dostęp za pomocą kilku bezpośrednich metod, które mogą być wystarczające czasami z OOP perspektywa.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-26 13:09:50
Ten post jest o Symbol()
, dostarczone z rzeczywistych przykładów mogłem znaleźć/zrobić i fakty & definicje mogłem znaleźć.
TLDR;
Symbol()
jest typem danych, wprowadzonym wraz z wydaniem ECMAScript 6 (ES6).
Są dwa ciekawostki o symbolu.
-
Pierwszy typ danych i jedyny typ danych w JavaScript, który nie ma literału
Każda zmienna, zdefiniowana za pomocą
Symbol()
, otrzymuje unikalną zawartość, ale nie jest tak naprawdę prywatne .Wszystkie dane mają swój własny Symbol , A Dla tych samych danych symbole będą tym samym . Więcej informacji w poniższym akapicie, w przeciwnym razie nie jest to TLRD; :)
Jak zainicjować symbol?
1. Aby uzyskać unikalny identyfikator z debuggowalną wartością
Możesz to zrobić w ten sposób:
var mySymbol1 = Symbol();
Lub w ten sposób:
var mySymbol2 = Symbol("some text here");
Łańcuch "some text here"
nie może być wyodrębniony z symbolu, to tylko opis do celów debugowania. Nie zmienia to w żaden sposób zachowania symbolu. Chociaż możesz console.log
to (co jest sprawiedliwe, ponieważ wartość jest do debugowania, aby nie pomylić tego dziennika z innym wpisem dziennika):
console.log(mySymbol2);
// Symbol(some text here)
2. Aby uzyskać symbol dla niektórych danych łańcuchowych
W tym przypadku wartość symbolu wynosi W rzeczywistości i w ten sposób dwa symbole mogą być niepowtarzalne.
var a1 = Symbol.for("test");
var a2 = Symbol.for("test");
console.log(a1 == a2); //true!
Nazwijmy te symbole" symbolami drugiego typu". Nie przecinają się one w żaden sposób z symbolami "pierwszego typu" (tj. tymi zdefiniowanymi za pomocą Symbol(data)
).
Następne dwa akapity dotyczą tylko symbolu pierwszego typu .
Jak mogę skorzystać z używania symbolu zamiast starszych typów danych?
Rozważmy najpierw obiekt, standardowy typ danych. Możemy tam zdefiniować kilka par klucz-wartości i mieć dostęp do wartości poprzez podanie klucza.
var persons = {"peter":"pan","jon":"doe"};
console.log(persons.peter);
// pan
Co jeśli mamy dwie osoby o nazwisku Peter?
Robi to:
var persons = {"peter":"first", "peter":"pan"};
To nie miałoby sensu.
Wygląda na to, że jest problem dwóch zupełnie różnych osób o tym samym imieniu. Odnieśmy się zatem do nowego Symbol()
. To jest jak osoba w prawdziwym życiu-każda osoba jest wyjątkowa , ale ich imiona mogą być równe. Zdefiniujmy dwie osoby.
var a = Symbol("peter");
var b = Symbol("peter");
Teraz mamy dwie różne osoby o tym samym imieniu. Czy nasze osoby naprawdę się różnią? Są, możesz sprawdzić to:
console.log(a == b);
// false
Jak na tym zyskamy?
Możemy zrobić dwa wpisy w Twoim obiekcie dla różnych osób i nie można ich w żaden sposób pomylić.
var firstPerson = Symbol("peter");
var secondPerson = Symbol("peter");
var persons = {[firstPerson]:"first", [secondPerson]:"pan"};
Uwaga:
Warto jednak zauważyć, że stringowanie obiektuJSON.stringify
spowoduje upuszczenie wszystkich par inicjowanych symbolem jako kluczem.
WykonanieObject.keys
nie zwróci takichSymbol()->value
par.
Użycie tej inicjalizacji jest absolutnie niemożliwe pomylić wpisy z pierwszą i drugą osobą. Wywołanie console.log
dla nich poprawnie wyświetli ich drugie imiona.
console.log(persons[a]);
// first
console.log(persons[b]);
// pan
Kiedy jest używana w obiekcie, czym różni się od definicji nieliczalnej właściwości?
Rzeczywiście, istniał już sposób na zdefiniowanie właściwości, która ma być ukryta przed Object.keys
i wyliczenie. Oto ona:
var anObject = {};
var fruit = "apple";
Object.defineProperty( anObject, fruit, {
enumerable: false,
value: "green"
});
Co to za różnica? Różnica polega na tym, że nadal można uzyskać Właściwość zdefiniowaną za pomocą Object.defineProperty
w zwykły sposób:
console.log(anObject[fruit]); //green
console.log(anObject["apple"]); //green
console.log(anObject.apple); //green
I jeśli zdefiniowano symbolem jak w poprzednim akapicie:
fruit = Symbol("apple");
Będziesz miał możliwość otrzymania jego wartości tylko wtedy, gdy znasz jego zmienną, tj.
console.log(anObject[fruit]); //green
console.log(anObject["apple"]); //undefined
console.log(anObject.apple); //undefined
Ponadto, zdefiniowanie innej właściwości pod kluczem "apple"
spowoduje, że obiekt upuści starszą (i jeśli zostanie zakodowany na twardo, może spowodować błąd). Koniec z jabłkami! Szkoda. Odwołując się do poprzedniego akapitu, symbole są unikalne i zdefiniowanie klucza jako Symbol()
sprawi, że wyjątkowe.
Konwersja i sprawdzanie typu
W przeciwieństwie do innych typów danych, nie można przekonwertować
Symbol()
na inny typ danych.Możliwe jest "stworzenie" symbolu na podstawie prymitywnego typu danych przez wywołanie
Symbol(data)
.-
Jeśli chodzi o sprawdzanie typu, nic się nie zmienia.
function isSymbol ( variable ) { return typeof someSymbol === "symbol"; } var a_Symbol = Symbol("hey!"); var totally_Not_A_Symbol = "hey"; console.log(isSymbol(a_Symbol)); //true console.log(isSymbol(totally_Not_A_Symbol)); //false
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-04 04:39:28