Estoy desarrollando una herramienta de instrumentación de código JavaScript.
Dado un fragmento de código, supongamos que necesito modificarlo para finalizar la siguiente tarea:
Tarea: Asignar una nueva propiedad a cada función cuando se invoca y acceder a la propiedad desde el cuerpo de la función.
Y solo puedo agregar nuevas líneas de código en el código original. NO se permiten otros cambios como la eliminación.
Teniendo en cuenta el siguiente ejemplo
foo(); function foo() { // All functions are assumed to have names }Puedo modificarlo agregando dos líneas de código como esta (básicamente asigno y accedo directamente a la propiedad agregada al referirme al nombre de la función):
foo.prop = ...; // give foo a new property foo(); function foo() { console.log(foo.prop); // access the property } Sin embargo, si hay otra función con el mismo nombre declarada dentro de foo , la solución anterior no funciona. Teniendo en cuenta el siguiente ejemplo.
foo(); function foo() { // All functions are assumed to have names function foo() {...} }Después de la modificación:
foo.prop = ... // give foo a new property foo(); function foo() { console.log(foo.prop); // property does not exist! function foo() {...} } Debido a la elevación de funciones, el foo externo se reemplaza por el foo interno, por lo tanto, no puedo acceder a la propiedad agregada usando el nombre de la función.
El uso de arguments.callee también puede fallar en modo estricto. Así que no es una opción para mí. ¿Hay algún método válido que pueda terminar esta tarea? ¿O es realmente imposible de hacer?
No estoy seguro si está buscando una vulnerabilidad o si esto es simplemente un ejercicio de aprendizaje. En cualquier caso, puede establecerlo en Object.prototype , y será heredado por foo ( y todos los demás objetos... que incluyen funciones ). Luego puede delete la propiedad cuando haya terminado con ella:
Object.defineProperty(Object.prototype, 'prop', { configurable: true, enumerable: true, writable: true, value: 'bar', }); // invoke foo(); // "bar" const obj = {}; console.log('obj', obj.prop); // "obj" "bar" obj.prop = 'baz'; console.log('obj', obj.prop); // "obj" "baz" // "undefine" the prop delete Object.prototype['prop']; console.log('obj', obj.prop); // "obj" "baz" // invoke again foo(); // undefined function foo() { console.log(foo.prop); function foo() {} }Puede usar la función de bind aquí:
function foo() { console.log("outer", this.prop); function foo() { console.log("inner", this.prop) } foo(); } const binded = foo.bind({prop: 2}); binded();Esto establece el objeto this en una función a un valor específico. ¡Tenga en cuenta que este objeto es diferente en la función foo interna!