2010-01-21 43 views
7

Tengo una pregunta extraña en la que necesito inyectar algunos javascript en otra función de JavaScript. Estoy usando un marco que está bloqueado por lo que no puedo cambiar la función existente.Inyectar javascript en una función de Javascript

Lo que tengo es algo como esto

función doSomething() {} ...

... ***

que pueda manipular el *** (arriba) sin embargo, no puedo cambiar la función doSomething ... En su lugar, necesito inyectar algunas líneas de código al final del código doSomething.

La razón por la que tengo que hacer esto es porque el marco personalizado llama a doSomething() y esto da como resultado que se devuelva una identificación del servidor que necesito extraer. Esta ID solo está referenciada dentro de la función doSomething, así que no puedo capturarla a menos que inyecte código a esa función (a menos que me haya perdido algo).

¿Hay alguna manera de hacerlo?

+3

¿Cómo está la función 'bloqueada'? – Lazarus

+0

Posible duplicado de [¿Hay alguna forma de ajustar todos los métodos de JavaScript con una función?] (Http://stackoverflow.com/questions/3919134/is-there-a-way-to-wrap-all-javascript-methods- with-a-function) –

Respuesta

0

Las funciones son valores de primera clase en Javascript, lo que significa que puede almacenarlas en variables (y de hecho, declarar que una función nombrada está asignando esencialmente una función anónima a una variable).

Usted debe ser capaz de hacer algo como esto:

function doSomething() { ... } 

var oldVersionOfFunc = doSomething; 
doSomething = function() { 

    var retVal = oldVersionOfFunc.apply(oldVersionOfFunc, args); 

    // your added code here 

    return retVal; 
} 

(Pero, puedo estar equivocado Mi Javascript está un poco oxidado;..))

+1

Si tengo la pregunta correcta, eso no ayudará aquí, ya que el problema es extraer el valor de una variable local a la que solo hace referencia dentro de 'doSomething'. Y la nueva versión de 'doSomething' no puede hacer referencia a las variables dentro de la anterior. –

5

un alias.

var oldDoSomething = doSomething; 
doSomething = function() { 
    // Do what you need to do. 
    return oldDoSomething.apply(oldDoSomething, arguments); 
} 
+0

necesita acceso a una variable que tiene el alcance de la función original – Matt

0

No puedo cambiar la función doSomething ... En vez necesito para inyectar alguna manera unas pocas líneas de código en el final del código doSomething

La inyección de unas pocas líneas en la parte menos del código doSomething suena como cambiar la función doSomething, para mí. Creo que, desafortunadamente, estás jodido.

(soy un poco confusa en todo esto, pero creo que las funciones son como las personas que se preocupan por esas cosas implementan ocultación de información en JavaScript, precisamente porque no se puede acceder a su alcance desde fuera de ellos.)

1
function doSomething() { ... } 
var oldVersionOfFunc = doSomething; 
doSomething = function() { 
    var retVal = oldVersionOfFunc.apply(oldVersionOfFunc, args); 
    // your added code here 
    return retVal; 
} 

Esto parece provocar un error (Demasiado recursividad)

function doSomething(){ document.write('Test'); return 45; } 
var code = 'myDoSomething = ' + doSomething + '; function doSomething() { var id = myDoSomething(); document.write("Test 2"); return id; }'; 
eval(code) 
doSomething(); 

Esto funciona para mí, aunque sea feo.

2

No estoy seguro de lo que quiere decir con "bloqueado" - JavaScript es interpretado por su navegador. Incluso si se ha modificado o codificado, puede copiar el origen de esa función desde el origen de la página del script. En ese punto, reasignará la función original a uno de su propio diseño, que contiene el código copiado más el suyo.

var id; 
var myFunction = function() { 
    // code copied from their source, which contains the variable needed 

    // insert your own code, such as for copying the needed value 
    id = theirIDvalue; 

    // return the value as originally designed by the function 
    return theirValue; 
}; 

theirObject.theirFunction = myFunction; 
3

Gracias por su respuesta. Cada respuesta me dio una pista y, como tal, se me ocurrió la siguiente solución.

<body> 
<script type="text/javascript"> 
    var val; 
    function doSomething(item1, item2) { 
     var id = 3; 
    } 
    function merge() { 
     var oScript = document.createElement("script"); 
     var oldDoSomething = doSomething.toString(); 
     oScript.language = "javascript"; 
     oScript.type = "text/javascript"; 
     var args = oldDoSomething.substring(oldDoSomething.indexOf("(") + 1, oldDoSomething.indexOf(")")); 
     var scr = oldDoSomething.substring(oldDoSomething.indexOf("{") + 1, oldDoSomething.lastIndexOf("}") - 1); 
     var newScript = "function doSomething(" + args + "){" + scr + " val = id; }"; 
     oScript.text = newScript; 
     document.getElementsByTagName('BODY').item(0).appendChild(oScript); 
    } 

    merge(); 

</script> 
<input type="button" onclick="doSomething();alert(val);" value="xx" /> 

+1

Una mejor solución (no requiere manipulación DOM, es Javascript puro): http://stackoverflow.com/a/9134757/39722 –

1

La alteración de la función mediante la colaboración con las cadenas de código fuente puede ser muy simple. Para hacerlo para una instancia específica, tratar:

eval(doSomething.toString().replace(/}\s*$/, ' return id; $&'); 

Ahora doSomething devuelve el ID. No soy normalmente un fan de eval, pero las técnicas normales de aspect oriented programming no se aplican aquí, debido al requisito de acceder a una variable local.

Si doSomething ya se devuelve un valor, intente:

eval(doSomething.toString().replace(/}\s*$/, ' window.someID = id; $&'); 

de convertir esto en una función, tenemos que hacer que el código evaluar en el ámbito global:

function insertCode(func, replacer, pattern) { 
    var newFunc = func.toString().replace(pattern, replacer); 
    with (window) { 
     eval(newFunc); 
    } 
} 
function after(func, code) { 
    return insertCode(func, function (old) { code + old }, /}\s*$/); 
} 
... 
after(doSomething, 'return id;'); 

Si desea reescribir métodos y funciones anónimas vinculadas a las variables, cambiar insertCodeBefore a:

function insertCode(funcName, replacer, pattern) { 
    var newFunc = eval('window.' + funcName).toString().replace(pattern, replacer); 
    eval('window.' + funcName + '=' + newFunc); 
} 
... 
function Foo() {} 
Foo.prototype.bar = function() { var secret=0x09F91102; } 
... 
after('doSomething', 'return id;'); 
after('Foo.prototype.bar', 'return secret;'); 

Tenga en cuenta que el primer argumento para las funciones ahora son cadenas. Podemos definir otras funciones:

function before(func, code) { 
    return insertCode(func, function (old) {old + code}, /^function\s+\w+\([^)]*\)\s+{/); 
} 
function around(func, beforeCode, afterCode) { 
    before(func, beforeCode); 
    after(func, afterCode); 
} 
+0

Esto no funcionará en el caso general, porque la función puede ejecutar un retorno en cualquier momento anterior, por lo que puede no llegar al código inyectado. –

Cuestiones relacionadas