varias una pasar node llamar funciones funcion evento entre ejemplo automaticamente anonima javascript

una - pasar variables entre funciones javascript



Invocar una función sin paréntesis (6)

Aquí hay un example para una situación particular:

window.onload = funcRef;

Aunque esa declaración en realidad no se invoca, dará lugar a una futura invocación .

Pero, creo que las áreas grises podrían estar bien para acertijos como este :)

Hoy me dijeron que es posible invocar una función sin paréntesis. Las únicas formas en que podía pensar era en usar funciones como apply o call .

f.apply(this); f.call(this);

Pero estos requieren paréntesis en apply y call dejándonos en el punto de partida. También consideré la idea de pasar la función a algún tipo de controlador de eventos como setTimeout :

setTimeout(f, 500);

Pero entonces la pregunta se convierte en "¿cómo invocar setTimeout sin paréntesis?"

Entonces, ¿cuál es la solución a este acertijo? ¿Cómo se puede invocar una función en Javascript sin usar paréntesis?


En ES6, tiene lo que se llama Tagged Template Literals .

Por ejemplo:

function foo(val) { console.log(val); } foo`Tagged Template Literals`;


Hay varias formas diferentes de llamar a una función sin paréntesis.

Supongamos que tiene esta función definida:

function greet() { console.log(''hello''); }

Luego, aquí hay algunas formas de llamar a greet sin paréntesis:

1. Como constructor

Con new puedes invocar una función sin paréntesis:

new greet; // parentheses are optional in this construct.

De MDN en el new oprador :

Sintaxis

new constructor[([arguments])]

2. En cuanto a la toString o el valor de la implementación

toString y valueOf son métodos especiales: se les llama implícitamente cuando es necesaria una conversión:

var obj = { toString: function() { return ''hello''; } } '''' + obj; // concatenation forces cast to string and call to toString.

Podrías (ab) usar este patrón para llamar a greet sin paréntesis:

'''' + { toString: greet };

O con valueOf :

+{ valueOf: greet };

2.b Anulación del valor de prototipo de función

Podría tomar la idea anterior para anular el método valueOf en el prototipo de Function :

Function.prototype.valueOf = function() { this.call(this); // Optional improvement: avoid `NaN` issues when used in expressions. return 0; };

Una vez que haya hecho eso, puede escribir:

+greet;

Y aunque hay paréntesis involucrados en la línea, la invocación de activación real no tiene paréntesis. Vea más sobre esto en el blog "Métodos de llamada en JavaScript, sin realmente llamarlos"

3. Como generador

Podría definir una función generadora (con * ), que devuelve un iterator . Puede llamarlo utilizando la sintaxis de propagación o con el for...of sintaxis.

Primero necesitamos una variante de generador de la función de greet original:

function* greet_gen() { console.log(''hello''); }

Y luego lo llamamos sin paréntesis:

[...{ [Symbol.iterator]: greet_gen }];

Normalmente los generadores tendrían una palabra clave de yield alguna parte, pero no es necesaria para que se llame a la función.

La última declaración invoca la función, pero eso también podría hacerse con la destructuring :

[,] = { [Symbol.iterator]: greet_gen };

o un for ... of construcción, pero tiene paréntesis propios:

for ({} of { [Symbol.iterator]: greet_gen });

Tenga en cuenta que también puede hacer lo anterior con la función de greet original, pero provocará una excepción en el proceso, después de que se haya ejecutado el greet (probado en FF y Chrome). Podrías gestionar la excepción con un try...catch block.

4. Como Getter

@ jehna1 tiene una respuesta completa sobre esto, así que dale crédito. Aquí hay una manera de llamar a una función sin paréntesis en el ámbito global, evitando el método __defineGetter__ desuso . Utiliza Object.defineProperty en Object.defineProperty lugar.

Necesitamos crear una variante de la función de greet original para esto:

Object.defineProperty(window, ''greet_get'', { get: greet });

Y entonces:

greet_get;

Reemplace la window con cualquiera que sea su objeto global.

Puede llamar a la función de greet original sin dejar un rastro en el objeto global como este:

Object.defineProperty({}, ''greet'', { get: greet }).greet;

Pero uno podría argumentar que tenemos paréntesis aquí (aunque no están involucrados en la invocación real).

5. Como función de etiqueta

Con ES6 puede llamar a una función pasándole un literal de plantilla con esta sintaxis:

greet``;

Consulte "Literales de plantillas etiquetadas" .

6. Como controlador proxy

En ES6, puede definir un proxy :

var proxy = new Proxy({}, { get: greet } );

Y luego leer cualquier valor de propiedad invocará greet :

proxy._; // even if property not defined, it still triggers greet

Hay muchas variaciones de esto. Un ejemplo más:

var proxy = new Proxy({}, { has: greet } ); 1 in proxy; // triggers greet


La forma más fácil de hacerlo es con el new operador:

function f() { alert(''hello''); } new f;

Si bien eso es poco ortodoxo y antinatural, funciona y es perfectamente legal.

El new operador no requiere paréntesis si no se utilizan parámetros.


Puedes usar getters y setters.

var h = { get ello () { alert("World"); } }

Ejecute este script solo con:

h.ello // Fires up alert "world"

Editar:

¡Incluso podemos hacer argumentos!

var h = { set ello (what) { alert("Hello " + what); } } h.ello = "world" // Fires up alert "Hello world"

Edición 2:

También puede definir funciones globales que se pueden ejecutar sin paréntesis:

window.__defineGetter__("hello", function() { alert("world"); }); hello; // Fires up alert "world"

Y con argumentos:

window.__defineSetter__("hello", function(what) { alert("Hello " + what); }); hello = "world"; // Fires up alert "Hello world"

Renuncia:

Como dijo @MonkeyZeus: nunca usarás este código en producción, sin importar cuán buenas sean tus intenciones.


Si aceptamos un enfoque de pensamiento lateral, en un navegador hay varias API que podemos abusar para ejecutar JavaScript arbitrario, incluida la llamada a una función, sin ningún paréntesis real.

1. location y javascript: protocolo:

Una de esas técnicas es abusar del protocolo javascript: en location asignación de location .

Ejemplo de trabajo

location=''javascript:alert/x281/x29''

Aunque técnicamente /x28 y /x29 siguen siendo paréntesis una vez que se evalúa el código, el carácter real ( y ) no aparece. Los paréntesis se escapan en una cadena de JavaScript que se evalúa en la asignación.

2. onerror y eval :

De manera similar, dependiendo del navegador, podemos abusar del onerror global, configurándolo como eval y arrojando algo que se convertirá en cadena a JavaScript válido. Este es más complicado, porque los navegadores son inconsistentes en este comportamiento, pero aquí hay un ejemplo para Chrome.

Ejemplo de trabajo para Chrome (no Firefox, otros no probados):

window.onerror=eval;Uncaught=0;throw'';alert/x281/x29'';

Esto funciona en Chrome porque throw''test'' pasará ''Uncaught test'' como primer argumento para onerror , que es JavaScript casi válido. Si en su lugar lanzamos throw'';test'' , pasará ''Uncaught ;test'' . ¡Ahora tenemos JavaScript válido! Simplemente defina Sin Uncaught y reemplace la prueba con la carga útil.

En conclusión:

Tal código es realmente horrible , y nunca debe usarse , pero a veces se usa en ataques XSS, por lo que la moraleja de la historia es no confiar en el filtrado de paréntesis para prevenir XSS. Usar un CSP para prevenir dicho código también sería una buena idea.