Znam wiele sposobów tworzenia obiektów JS, ale nie znałem tego Object.create(null)
.
Pytanie:
czy to dokładnie to samo, co:
var p = {}
vs
var p2 = Object.create(null);
?
źródło
Znam wiele sposobów tworzenia obiektów JS, ale nie znałem tego Object.create(null)
.
Pytanie:
czy to dokładnie to samo, co:
var p = {}
vs
var p2 = Object.create(null);
?
Nie są równoważne. {}.constructor.prototype == Object.prototype
while Object.create(null)
nie dziedziczy niczego, a zatem nie ma żadnych właściwości.
Innymi słowy: obiekt JavaScript dziedziczy Object domyślnie, chyba że wyraźnie go utworzyć z zerową jako prototyp, jak: Object.create(null)
.
{}
zamiast tego byłby równoważny Object.create(Object.prototype)
.
W Chrome Devtool widać, że Object.create(null)
nie ma on żadnej __proto__
właściwości, podczas gdy {}
tak.
Zdecydowanie nie są równoważne. Piszę tę odpowiedź, aby pełniej wyjaśnić, dlaczego ma to znaczenie.
var p = {};
Tworzy obiekt, który dziedziczy właściwości i metody z Object
.
var p2 = Object.create(null);
Tworzy obiekt, który niczego nie dziedziczy.
Jeśli używasz obiektu jako mapy i tworzysz obiekt za pomocą powyższej metody 1, musisz zachować szczególną ostrożność podczas wyszukiwania na mapie. Ponieważ właściwości i metody z Object
są dziedziczone, kod może zostać uruchomiony w przypadku, gdy w mapie znajdują się klucze, których nigdy nie wstawiono. Na przykład, gdybyś przeszukał toString
, znalazłbyś funkcję, nawet jeśli nigdy nie umieściłeś tam tej wartości. Możesz to obejść w ten sposób:
if (Object.prototype.hasOwnProperty.call(p, 'toString')) {
// we actually inserted a 'toString' key into p
}
Zauważ, że można coś przypisać p.toString
, po prostu nadpisuje odziedziczoną toString
funkcję p
.
Zauważ, że nie możesz tego zrobić tylko p.hasOwnProperty('toString')
dlatego, że mogłeś wstawić klucz „hasOwnProperty” do p
, więc zmuszamy go do użycia implementacji w Object
.
Z drugiej strony, jeśli użyjesz metody 2 powyżej, nie będziesz musiał martwić się o Object
pojawienie się rzeczy na mapie.
Nie możesz sprawdzić istnienia właściwości za pomocą prostego if
przykładu:
// Unreliable:
if (p[someKey]) {
// ...
}
Wartością może być pusty ciąg, może to być false
, lub null
, lub undefined
, lub 0
, lub NaN
, itd. Aby sprawdzić, czy właściwość w ogóle istnieje, nadal musiałbyś jej użyć Object.prototype.hasOwnProperty.call(p, someKey)
.
if (someKey in p) {
Object.create(null)
. Wolę nie przyjmować takich założeń, nawet jeśli miałeś absolutną rację, że użyłObject.create(null)
, kod może się zmienić, obiekt można zastąpić takim, któryObject
w pewnym momencie dziedziczy .hasOwnProperty
zawsze działa.{}
jest o wiele bardziej rozpowszechniony niż toObject.create(null)
, że jeśli twój kod przypadkowo przejmie w tym momencie odziedziczoną właściwość, prawdopodobnie będziesz się martwić o znacznie większe błędy. Widzę tylko osoby używające Object.create (null) jako niewielkiej optymalizacji.!!p[key]
działa dobrze zObject.create(null)
. Ale teżhasKey = (key, input) => Object.prototype.hasOwnProperty.call(input, key)
nie jest złyp
ponieważ każda metoda może zostać wstawiona i dlatego nie jest bezpieczna.Tworzenie obiektów za pomocą
{}
use spowoduje utworzenie obiektu, którego prototypObject.prototype
dziedziczy podstawowe funkcje zObject
prototypu, podczas gdy tworzenie obiektów za pomocą użyciaObject.create(null)
spowoduje utworzenie pustego obiektu, którego prototyp jest pusty.źródło
Jeśli ktoś szuka implementacji
Object.create(null)
, wystarczy wiedzieć, jak to działa. Jest napisany w__proto__
sposób niestandardowy i dlatego nie polecam tego .Uwaga : napisałem to z ciekawości i jest napisane tylko prostymi słowami, na przykład nie przenoszę deskryptorów właściwości z drugiego obiektu do obiektu zwracanego.
źródło
__proto__
będzie teraz oficjalnie częścią języka.-1
warguments.length>0?arguments[0]:-1;
?Object
prototyp jest zachowywany, jeśli nie zostanie podany pierwszy argument. Nazwy zmiennych mogłyby być tutaj znacznie lepsze.Kiedy tworzysz obiekt za pomocą Object.create (null), oznacza to, że tworzysz obiekt bez prototypu. null oznacza tutaj koniec łańcucha prototypów. Niemniej jednak podczas tworzenia obiektu takiego jak {} zostanie dodany prototyp obiektu. Dlatego są to dwa różne obiekty, jeden z prototypem, drugi bez prototypu. Mam nadzieję, że to pomoże
źródło