Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

187
Views
No se puede acceder al atributo de función dentro de la función de decoración

En el siguiente código, intento agregar decoradores a una función. Por ciertas razones, me gustaría mostrar el atributo de función "nombre". Sin embargo, no tengo acceso a él tan pronto como estoy en las funciones individuales. Además, no estoy seguro de por qué las funciones se llaman de abajo hacia arriba. ¿Cuáles son las razones de todos los puntos mencionados y cómo puedo evitarlos?

 let rectangleArea = (length, width) => { return length * width; } const countParams = (fn) => { return (...params) => { console.log('countParams', fn.name) if (params.length !== fn.length) { throw new Error(`Incorrect number of parameters for ${fn.name}!`); } return fn(...params); } } const requireIntegers = (fn) => { return (...params) => { console.log('requireIntegers', fn.name) params.forEach(param => { if (!Number.isInteger(param)) { throw new TypeError(`Params must be integers at ${fn.name}!`); //Can't access fn.name } }); return fn(...params); } } //Why running from bottom to top? rectangleArea = countParams(rectangleArea); rectangleArea = requireIntegers(rectangleArea); console.log(rectangleArea(20, 30, "hey"));

about 4 years ago · Juan Pablo Isaza
3 answers
Answer question

0

La primera vez que crea una función decorada para una función determinada, la función devuelta no tiene nombre, es anónima. Entonces, cuando pase esa función decorada para que se decore nuevamente, fn será esa función anónima.

Para resolver esto, asigne el nombre de la función fn también a la función decorada devuelta. De esa manera, el nombre se mantendrá incluso cuando decores esa función una y otra vez...

Aquí hay una función auxiliar que asignará la propiedad de nombre a una función determinada:

 const setName = (deco, value) => { Object.defineProperty(deco, "name", {value, writable: false}); return deco; } let rectangleArea = (length, width) => { return length * width; } const countParams = (fn) => { return setName((...params) => { console.log('countParams', fn.name) if (params.length !== fn.length) { throw new Error(`Incorrect number of parameters for ${fn.name}!`); } return fn(...params); }, fn.name); } const requireIntegers = (fn) => { return setName((...params) => { console.log('requireIntegers', fn.name) params.forEach(param => { if (!Number.isInteger(param)) { throw new TypeError(`Params must be integers at ${fn.name}!`); //Can't access fn.name } }); return fn(...params); }, fn.name); } rectangleArea = countParams(rectangleArea); rectangleArea = requireIntegers(rectangleArea); console.log(rectangleArea(20, 30, "hey"));

Por qué las funciones se llaman de abajo hacia arriba.

Porque en tu decorador el último paso es llamar a fn .

Es posible que fn sea una función ya decorada, por lo que es normal que las decoraciones anteriores de la función se ejecuten más tarde .

Es como envolver un regalo de cumpleaños varias veces, cada vez con un color diferente de papel de regalo. Cuando tu amigo lo desembale, podrá ver los colores del papel de regalo en orden inverso al orden en que los habías aplicado.

about 4 years ago · Juan Pablo Isaza Report

0

¿Así que quieres hacer algo adicional con tus decoradores? ¿Necesitan algún comportamiento común? Hemos demostrado que ya sabemos cómo hacerlo: con decoradores. ¡Tus decoradores necesitan decoradores propios!

Aquí escribo un decorator-decorator keep que toma una función de decorador y devuelve una nueva función de decorador que conserva el name y las propiedades de length de la función que se le pasó. (¡Di eso cinco veces mas rapido!)

Utiliza la misma técnica que la respuesta de trincot, pero es menos intrusivo, ya que simplemente puede envolver las funciones del decorador tal como lo haría con las subyacentes. Aquí hago eso en el momento de la definición, ya que nunca queremos que estos decoradores tengan este comportamiento, pero puedes hacerlo como quieras.

 let rectangleArea = (length, width) => { return length * width; } const keep = (decorator) => (fn) => Object .defineProperties (decorator (fn), { name: {value: fn .name, writable: false}, length: {value: fn .length, writable: false} }) const countParams = keep ((fn) => { return (...params) => { console.log('countParams', fn.name) if (params.length !== fn.length) { throw new Error(`Incorrect number of parameters for ${fn.name}!`); } return fn(...params); } }) const requireIntegers = keep ((fn) => { return (...params) => { console.log('requireIntegers', fn.name) params.forEach(param => { if (!Number.isInteger(param)) { throw new TypeError(`Params must be integers at ${fn.name}!`); //Can't access fn.name } }); return fn(...params); } }) //Why running from bottom to top? -- answered by @balastrong rectangleArea = countParams(rectangleArea); rectangleArea = requireIntegers(rectangleArea); console.log(rectangleArea(20, 30)); console.log(rectangleArea(20, 30, "hey"));
 .as-console-wrapper {max-height: 100% !important; top: 0}

El nombre keep originalmente era keepName antes de que me diera cuenta de que personalmente también querría que la función mantuviera intacta la aridad. No se me ocurrió un nombre claro y útil para esto... lo cual es una gran señal de advertencia para mí. Así que puede haber algo mal con este diseño.

about 4 years ago · Juan Pablo Isaza Report

0

No es de abajo hacia arriba, es el orden que establezcas.

Con tus decoradores, básicamente hiciste esto:

 requireIntegers(countParams(rectangleArea(20, 30, "hey"))).

Lo que significa que primero ejecuta requireIntegers pasándolo como entrada todo lo demás ( countParams(rectangleArea(20, 30, "hey")) ).

Luego, ve el registro de la consola y el error como params.forEach escanea los parámetros y encuentra 'hey' que no es un número.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!