Ein JS __proto__ „lustiger“ Fakt

Nov 26 2022
Wenn Sie mir lange genug folgen, wissen Sie bereits, wie sehr ich immer gegen __proto__ war, und doch, seit es vor langer Zeit zum ECMAScript-Standard gelangt ist, gibt es immer noch seltene Fälle, in denen ich zumindest seine Verwendung zum Branding eines Objekts finde akzeptabel: Abgesehen von der Leistung und bitte beachten Sie, dass ich die Verwendung von __proto__ überhaupt nicht in freier Wildbahn vorschlage, dieser Beitrag existiert aus anderen Gründen. Objekt.
Foto von Mark Williams auf Unsplash

Wenn Sie mir lange genug gefolgt sind, wissen Sie bereits, wie sehr __proto__ich immer dagegen war, und doch, seit es vor langer Zeit zum ECMAScript-Standard wurde, gibt es immer noch seltene Fälle, in denen ich zumindest seine Verwendung zum Branding eines Objekts akzeptabel finde :

const factory = (fields, {prototype} = Object) => ({
  __proto__: prototype,
  ...fields
});

// mimic an <a /> reference
factory({href: '/'}, HTMLAnchorElement);

In Firefox schneidet __proto__ besser ab als die neue Klasse

Abgesehen von der Leistung, und bitte beachten Sie, dass ich die Verwendung von __proto__überhaupt nicht in freier Wildbahn vorschlage, existiert dieser Beitrag aus anderen Gründen.

Objekt.prototype.__proto__

Ich bin mir ziemlich sicher , dass jeder weiß, was __proto__ accessor tut , also möchte ich Ihnen eine Herausforderung vorschlagen … und ja, das ist alles gültiges JS:

class Test {}
const __proto__ = Test.prototype;

// what do these operations return?
({__proto__} instanceof Test);
({__proto__: __proto__} instanceof Test);
({"__proto__": __proto__} instanceof Test);
({["__proto__"]: __proto__} instanceof Test);

// what do these operations return?
({__proto__}.__proto__ === Test.prototype);
({__proto__: __proto__}.__proto__ === Test.prototype);
({"__proto__": __proto__}.__proto__ === Test.prototype);
({["__proto__"]: __proto__}.__proto__ === Test.prototype);

Wenn Sie diese Snippets nicht selbst ausgeführt haben, um die Antwort zu erfahren, kann ich Ihnen dabei helfen! In der ersten Herausforderung wird die Ausgabe false, true, trueund falsewieder sein, und der Grund dafür ist, dass sowohl {__proto__}als auch als eigene Eigenschaft definiert{["__proto__"]} sind , während die Zuweisung per Syntax, ohne Verwendung spezieller Syntaxfunktionen, sogar mit Anführungszeichen, tatsächlich durch den Accessor geht.Object.prototype.__proto__

Andererseits spielt es bei der zweiten Herausforderung (all true) keine Rolle, ob wir __proto__direkt oder als zugreifen ["__proto__"], sodass es im Grunde keine Symmetrie gibt, wie wir den __proto__Setter auslösen können, von der Art, wie wir den __proto__Getter einmal auslösen können es ist entweder ein eigenes Eigentum oder ein magisches Erbschaftstor.

… und nicht nur __proto__

Ich habe mich selbst nicht überprüft, aber ich glaube, dass jeder Legacy- __xxx__Special-Accessor unter dem gleichen __proto__Fluch leidet, also seien Sie bitte vorsichtig, wenn Sie die neueste coole JS-Syntax verwechseln, um Eigenschaften mit Ihren tatsächlichen Absichten und Erwartungen zuzuweisen, da die Dinge leicht banal werden könnten, wenn Sie es versuchen Seien Sie schlau bei der Zuweisung dieser Eigenschaften .

Und das ist alles Leute!

Die einzige Erkenntnis aus diesem Beitrag lässt sich wahrscheinlich wie folgt zusammenfassen:

  • Verwenden Sie keine alten, noch funktionierenden Teile der Sprache, wenn Sie heute oder morgen Überraschungen darüber vermeiden möchten, wie sich diese mit der neuen Syntax verhalten
  • bevorzugen Sie explizit (und leider langsamer) Object.setPrototypeOf, wenn das manuelle Setzen des Prototyps eines Objekts unbedingt erforderlich ist, verwenden Sie jedoch in allen anderen Fällen, wann immer dies möglich ist, Klassen
  • Löschen Sie diesen Beitrag aus Ihrem Gedächtnis oder verkleinern Sie ihn zu einem kurzen Satz wie: „ Ich sollte niemals __proto__in meinem Code verwenden “ und machen Sie weiter und lernen Sie schicke neue Sachen, die Ihr Gehirn oder Ihre Gefühle nicht durcheinander bringen