¿Cómo agregar properties al context de ejecución actual dinámicamente en JavaScript?

Estoy leyendo un libro de text del lenguaje JavaScript. Y mientras estudio el tema del cierre, surgió la siguiente pregunta.

Considerando esta function:

function foo() { extractPropsToCurrentContext({'prop1' : 'hello', 'prop2' : 123}); } 

Quiero el resultado del código anterior, es igual a :

 function foo() { var prop1 = 'hello'; var prop2 = 123; } 

Entonces, mi pregunta es, ¿cómo implementar la function extractPropsToCurrentContext (/ * Object * /)?

Solo para aclarar, quiero extraer esas properties del object en el context de ejecución , no debajo del puntero 'this'. (Entonces, los objects extraídos deberían ser privados dentro de esa function).

Otra cosa para aclarar, no puedes asumir que el foo se invocará con 'nuevo'. (como nuevo foo ())

Actualizar:

Quiero decir, ¿hay alguna posibilidad de que podamos usar trucos hábiles para desviar la restricción del browser, para acercarnos al resultado que queremos? Como, hace años, inventamos JSONP para dominios cruzados, tirando largo para empujar posts, etc.

2 Solutions collect form web for “¿Cómo agregar properties al context de ejecución actual dinámicamente en JavaScript?”

Quiero extraer esas properties del object en el context de ejecución

Un context de ejecución en realidad consta de tres cosas:

  • el ThisBinding , que dijiste que no querías alterar o extender.

  • VariableEnvironment , que contiene las variables y funciones declaradas. Esto es lo que su código igual cambiaría. Puedes modificarlo con el siguiente truco:

     function getVariableDeclaration(obj) { return "var " + Object.keys(obj).map(function(name) { return name + " = " + JSON.stringify(obj[name]); }).join(",\n ") + ";"; } function foo() { eval(getVariableDeclaration({'prop1' : 'hello', 'prop2' : 123})); debugger; } foo(); 

    Sin embargo, esto funciona solo en modo no estricto. Ver §10.4.2 para más detalles. Además, este truco actualmente está restringido a los valores serializables de JSON, sería mucho más feo si necesitaras asignar valores arbitrarios: eval debe usarse en el entorno que deseas alterar.

  • LexicalEnvironment , que contiene los enlaces de identificador actuales (y puede cambiar durante la ejecución en contraste con VariableEnvironment ). Esto no es exactamente lo que podría querer, pero se puede modificar muy fácilmente a través de la Declaración with :

     function foo() { with ({'prop1' : 'hello', 'prop2' : 123}) { debugger; } } foo(); 

    Nuevamente, no funciona en modo estricto. Ver §12.10 y §10.2.2.3 sobre cómo funciona y sombras de otras vinculaciones.

Como puede ver, el modo estricto prohíbe cualquier cambio en un context de ejecución (no global), ya que esto hace que los enlaces no sean estáticos y no optimizables. La mayoría del código también se vuelve más difícil de entender, por lo que, en general, se considera una mala práctica.

Está bien reflexionar sobre estos hackeos desde un punto de vista académico (para entender el funcionamiento del lenguaje), pero nunca debes usarlos en producción. Cualquier cosa que tenga en mente que requiera tales técnicas, hay mejores soluciones.

Solo quería compartir mi incómoda solución. La idea es build una nueva function a partir del rest de la function primaria y llamarla en eval .

 function cc(fnname, ctxname) { 'use strict'; var __evalfn = function () { 'use strict'; var __fn = __fnname, __ctx = __ctxname, __fnStr = __fn.toString(), __cccall = 'return eval(cc("'+__sfnname+'", "'+__sctxname+'"));', __cccallPos = __fnStr.indexOf(__cccall), __newFn = '(function () { var ', __decl = [], __restBody; if (__cccallPos === -1) { throw new Error("Can't find cc call"); } __restBody = __fnStr.slice(__cccallPos+__cccall.length); for (var __k in __ctx) { __decl.push(__k + '=' + __sctxname + '['+JSON.stringify(__k)+']'); } __newFn += __decl.join(',') + ';'; __newFn += __restBody; __newFn += ')()'; return eval(__newFn); }, __evalStr = __evalfn.toString() .replace(/__fnname/g, fnname) .replace(/__sfnname/g, JSON.stringify(fnname)) .replace(/__ctxname/g, ctxname) .replace(/__sctxname/g, JSON.stringify(ctxname)); return '('+__evalStr+')()'; } var fn = function () { var a=10, ctx = {'b':10, 'c':'hello'}; return eval(cc("fn", "ctx")); console.log(a,b,c); return a+b; }; > fn(); > 10 10 "hello" > <- 20 

Te requerirá poner return eval(cc("fn", "ctx")); en tu function. fn es el nombre de una function de retención variable en la que utiliza cc . ctx es un nombre de object que contiene nuevas vinculaciones. Una ventaja de cc es que permite cualquier valor en ctx , desde numbers y cadenas hasta objects creados mediante constructores definidos por el usuario.

Javascript tiene muchos buenos JS marco (como Node.js AngularJS Vue.js React.js) es el mejor lenguaje de script.