Javascript: How change function call params on the fly?
I'm receiving some 'body' content from a jquery's json call, where I can get the unique javascript element returned by doing:
script_element = $(data.body)[1]
This equals to:
<script type="text/javascript">
updater('foo', 'bar', {}, '0', constant='');
</script>
So, typeof script_element
returns "object"
And, if I run script_element.innerText
, I can get:
updater('foo', 'bar', {}, '0', constant='');
After receiving this script, what I'm doing right now is just run an eval
on it, but searching around I couldn't get a way to run eval
changing function call params.
What I'm trying to do is change the third
param of the call, in t开发者_C百科his case the {}
, that can change depending on the return of the json call, so I can't just search for {}
.
I could also do script_element.text.split(',')[2]
for example, and change this text on the fly, but I was thinking there should be a better way to do this.
I don't know if javascript can recognize and treat a "future method call", but still think there should be a better way.
Any idea?
What you could do is shadowing the function so as to be able to alter the third argument. You ought to define that shadowing function before fetching the JSON.
var originalUpdater = updater; // keep old function to call
// overwrite (shadowing)
updater = function(a, b, c, d, e) {
// change c appropriately here
originalUpdater(a, b, c, d, e);
}
Then you can still just eval
it (which is not very safe, but that's not your point if I'm not mistaking), and it will call the shadow function.
A more generic shadowing method would be along the lines of:
var originalUpdater = updater; // keep old function to call
// overwrite (shadowing)
updater = function() {
// change arguments[2] appropriately here
originalUpdater.apply(this, arguments);
}
Fiddle: http://jsfiddle.net/n7dLX/
Change the server. Rather than returning
<script type="text/javascript">
updater('foo', 'bar', {}, '0', constant='');
</script>
Return
{
"method": "updater",
"params": [
"foo", "bar", {}, "0", ''
]
}
Assuming that you cannot change what is being sent over from the server, you can simply run through the innerText
with a regular expression and pass update the HTML before you insert it.
var replacer = /\w+\(([^()]+)\)/gi;
script_element.innerText.replace(replacer, function(matched_text, func_params){
var orig_func_params = func_params;
// Make changes to func_params here.
return matched_text.replace(orig_func_params, func_params);
});
This can be functionized by doing the following:
var replacer = /\w+\(([^()]+)\)/gi;
function replace_arg(script_element, arg_index, replacement_value) {
script_element.innerHTML = script_element.innerHTML.replace(replacer,
function(matched_text, func_params){
var orig_func_params = func_params;
func_params = func_params.split(",");
if (arg_index >= func_params.length) {
throw new RangeError(arg_index + " is out of range. Total args in function:" + func_params.length);
}
func_params[arg_index] = JSON.stringify(replacement_value);
return matched_text.replace(orig_func_params, func_params.join(","));
});
return script_element;
}
This can be called in this way:
script_element = replace_arg(script_element, 3, {"new":"arg"});
I don't understand what you are doing, but in general if you don't want to rely on the order of parameters make the function take one parameter that is an object whose properties are the parameters:
function add(params) {
var a = params.hasOwnProperty("paramA") ? params.paramA : 0;
var b = params.hasOwnProperty("paramB") ? params.paramB : 0;
return a + b;
}
add({paramA: 1, paramB: 2});
In this case you should use hasOwnProperty to check if the function was passed the parameter you are looking for before trying to access it.
精彩评论