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);
?
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);
?
Odpowiedzi:
Nie są równoważne. {}.constructor.prototype == Object.prototypewhile 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 Objectsą 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ą toStringfunkcję 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 Objectpojawienie się rzeczy na mapie.
Nie możesz sprawdzić istnienia właściwości za pomocą prostego ifprzykł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).
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óry Objectw pewnym momencie dziedziczy . hasOwnPropertyzawsze działa.
{}jest o wiele bardziej rozpowszechniony niż to Object.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 z Object.create(null). Ale też hasKey = (key, input) => Object.prototype.hasOwnProperty.call(input, key)nie jest zły
pponieważ każda metoda może zostać wstawiona i dlatego nie jest bezpieczna.
Tworzenie obiektów za pomocą {}use spowoduje utworzenie obiektu, którego prototyp Object.prototypedziedziczy podstawowe funkcje z Objectprototypu, podczas gdy tworzenie obiektów za pomocą użycia Object.create(null)spowoduje utworzenie pustego obiektu, którego prototyp jest pusty.
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 .
function objectCreateMimic()
{
/*optional parameters: prototype_object, own_properties*/
var P = arguments.length>0?arguments[0]:-1;
var Q = arguments.length>1?arguments[1]:null;
var o = {};
if(P!==null && typeof P === "object")
{
o.__proto__ = P;
}
else if(P===null)
{
o.__proto__ = null;
}
if(Q!==null && typeof Q === "object")
{
for(var key in Q)
{
o[key] = Q[key];
}
}
return o;
}
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.
__proto__będzie teraz oficjalnie częścią języka.
-1w arguments.length>0?arguments[0]:-1;?
Objectprototyp 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
if (someKey in p) {