$ mol_strict: ¿Qué tal yo [object Object] tu NaN indefinido?

Hola, mi nombre es Dmitry Karlovsky y yo ... no perdono errores. Tan pronto como lo veo, inmediatamente lanzo algo extremadamente pesado. Y lo duro que es el trabajo de un programador JS ...







class Foo extends Object {}
const foo = new Foo

`, ${ foo }!`
// " [object Object]!"

`     ${ foo / 1000 }  .`
// "     NaN  ."

`  "${ 'foo'[4] }" - .`
// "  "undefined" - ."

`  ${ foo.length - 1 }     .`
// "  NaN     ."
      
      





Hay varias formas de aliviar su sufrimiento.







  1. Cúbrase con un texto mecanografiado. Pero en tiempo de ejecución, los pies todavía permanecen descalzos y alguien siempre los pisa.
  2. Para imponer cheques. Pero vacila un poco y el rastrillo de tiempo de ejecución golpea inmediatamente la cabeza.
  3. Arreglar JS. Ni siquiera esperes.
  4. Corrige el tiempo de ejecución de JS. Bueno, pensemos ...


Los problemas de escritura dinámica de JS surgen por 2 razones principales:







  • Encasillado automático (y en ocasiones inapropiado) cuando se utiliza un valor de un tipo en un contexto destinado a otro.
  • Devuelve undefined como el valor de los campos no declarados.


Tratemos primero el primer problema. JS está diseñado de tal manera que no podemos arreglar la conversión de tipos primitivos de ninguna manera. Pero tenemos un control total sobre la fundición de objetos. Por lo tanto, parcheemos el prototipo global de todos los objetos para que ninguno de los objetos pueda ser lanzado por defecto:







Object.prototype[ Symbol.toPrimitive ] = function() {
    throw new TypeError( `Field Symbol(Symbol.toPrimitive) is not defined` )
}
      
      





, , Symbol.toPrimitive



.







, . - … - ! … , .







- , . JS — . , :







export let $mol_strict_object = new Proxy( {}, {

    get( obj: object, field: PropertyKey, proxy: object ) {
        const name = JSON.stringify( String( field ) )
        throw new TypeError( `Field ${ name } is not defined` )
    },

})
      
      





, prototype



Object



, , . Object.prototype



null



. Object



:













:







for( const name of Reflect.ownKeys( $ ) ) {
    // ...
}
      
      





, :







const func = Reflect.getOwnPropertyDescriptor( globalThis, name )!.value
if( typeof func !== 'function' ) continue
if(!( 'prototype' in func )) continue
      
      





, globalThis[name]



, .







, Object



:







const proto = func.prototype
if( Reflect.getPrototypeOf( proto ) !== Object.prototype ) continue
      
      





, , Object.prototype



:







Reflect.setPrototypeOf( proto, $mol_strict_object )
      
      





, , . , .







, , Object, , EventTarget, .







CSSStyleDeclaration



: ( , ), , , 89 style



dom-:







( <div style={{ color: 'red' }} /> ).outerHTML // <div></div>
      
      





.







… :







class Foo {}
      
      





. :







class Foo extends Object {}
      
      





… . Object



:







globalThis.Object = function $mol_strict_object( this: object, arg: any ) {
    let res = Object_orig.call( this, arg )
    return this instanceof $mol_strict_object ? this : res
}

Reflect.setPrototypeOf( Object, Reflect.getPrototypeOf({}) )
Reflect.setPrototypeOf( Object.prototype, $mol_strict_object )
      
      





, Object



, .







, ...







class Foo extends Object {}
const foo = new Foo

`, ${ foo }!`
// TypeError: Field "Symbol(Symbol.toPrimitive)" is not defined

`     ${ foo / 1000 }  .`
// TypeError: Field "Symbol(Symbol.toPrimitive)" is not defined

`  "${ 'foo'[4] }" - .`
// TypeError: Field "4" is not defined

`  ${ foo.length - 1 }     .`
// TypeError: Field "length" is not defined
      
      





, , :







, - . — .







, : JavaScript ?.







: $mol_strict.







NPM - :







import "mol_strict"
      
      





:







require("mol_strict")
      
      





$mol : $mol: Usage from NPM ecosystem.







JS , :









, _jinnin , JS, UX .








All Articles