Un hecho "divertido" de JS __proto__

Nov 26 2022
Si me ha seguido el tiempo suficiente, ya sabe cuánto en contra de __proto__ siempre he estado y, sin embargo, desde que llegó al estándar ECMAScript hace mucho tiempo, todavía hay raras ocasiones en las que encuentro al menos su uso para marcar un objeto. aceptable: dejando de lado el rendimiento, y tenga en cuenta que no estoy sugiriendo el uso de __proto__ en absoluto, esta publicación existe por otras razones. Objeto.
Foto de Mark Williams en Unsplash

Si me ha seguido el tiempo suficiente, ya sabe cuánto en contra __proto__siempre he estado y, sin embargo, desde que se convirtió en el estándar ECMAScript hace mucho tiempo, todavía hay raras ocasiones en las que encuentro aceptable al menos su uso para marcar un objeto. :

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

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

En Firefox, __proto__ puntúa mejor que la nueva Clase

Dejando a un lado el rendimiento, y tenga en cuenta que no estoy sugiriendo el uso de __proto__en absoluto, esta publicación existe por otras razones.

Objeto.prototipo.__proto__

Estoy bastante seguro de que todo el mundo sabe lo que hace __proto__ accessor , así que me gustaría proponerte un desafío... y sí, todo esto es JS válido:

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);

Si no ha ejecutado estos fragmentos para saber la respuesta, ¡puedo ayudarlo con eso! En el primer desafío, la salida será false, y otra vez true, y la razón es que ambos y están definidos como propiedad propia , mientras que la asignación a través de la sintaxis, sin usar características especiales de sintaxis, incluso con comillas alrededor, pasa en realidad a través del descriptor de acceso.truefalse{__proto__}{["__proto__"]}Object.prototype.__proto__

Por otro lado, en el segundo desafío (todos true) realmente no importa si accedemos __proto__directamente o como ["__proto__"], por lo que básicamente hay cero simetría en la forma en que podemos activar el __proto__setter, desde la forma en que podemos activar el __proto__getter una vez . es una propiedad propia o una puerta mágica de herencia.

… y no solo __proto__

No me he comprobado a mí mismo, pero creo que todos los accesores __xxx__especiales heredados sufren la misma __proto__maldición, así que tenga cuidado al mezclar la sintaxis JS más reciente para asignar propiedades con su intención y expectativas reales, ya que las cosas podrían volverse locas si intenta Sea inteligente al asignar estas propiedades .

¡Y eso es todo amigos!

La única conclusión de esta publicación probablemente se resuma así:

  • no utilice partes del lenguaje heredadas que aún funcionan, si desea evitar sorpresas hoy o mañana sobre cómo se comportan con la nueva sintaxis
  • prefiera explícito (y desafortunadamente más lento) Object.setPrototypeOfsiempre que se requiera estrictamente configurar manualmente el prototipo de un objeto, pero use clases en todos los demás casos siempre que sea posible
  • borre de su memoria esta publicación o redúzcala a una oración corta como: " Nunca debería usar __proto__en mi código " y avance aprendiendo cosas nuevas y elegantes que no arruinen su cerebro o sus sentimientos