开发者

Passing unknown amounts of variables using through a string string and eval and multiple functions and all sorts

In short, I want to use an object literal to allow me to pass a unknown amount of variables in any order to a function. Whilst this is not big deal in theory, in my code, this object literal is passed to a second function called on_change.

on_change works by comparing an element's innerHTML to a string; If it is the same, it sets a timeout to call the function again. If the element's innerHTML is different from the string, then the third parameter is executed, this will either be a function or a string. either way it will execute. I have tested this function plenty and used it for a while now.

However, I cannot seem to get the object literal to flow through the function calls...

var params = { xpos:'false'};
on_change('window_3_cont_buffer','','
if(Window_manager.windows[3].window_cont_buffer.getElementsByTagName(\'content\')[0].getElementsByTagName(\'p\')[0].innerHTML == \'ERROR\'){
alert(Window_manager.windows[3].window_cont_buffer.getElementsByTagName(\'content\')[0].getElementsByTagName(\'p\')[1].innerHTML);
return false;
} else { 
Window_manager.windows[3].load_xml(\'location/view.php?location_ID=3\', \'\', ' + params + ' ); }
');

I call this as part of the form submission. After this line, I then call a function to load some content via ajax, which works fine and will trigger the code from the on_change function.

I have tested the load_xml function, it is able to call alert(param.xpos) and get the correct response. I can even added in a check for being undefined so that rest of the times I call load_xml I don't get swamped with alerts.

The load_xml function first sets up the on_change function, then calls the function to load the content to a hidden div. Once the AJAX request has updated that DIV, the on_change function should now call the parse_xml function. This pulls out the information from the xml file. However... The idea of this object literal param is that it can tel开发者_如何学Gol this parse_xml function to ignore certain things.

on_change("window_" + this.id + "_cont_buffer", "", "Window_manager.windows[" + this.id + "].parse_xml('" + param + "')");

This is part of load_xml, it works perfectly fine, even with the param bit in there. except, parse_xml does not seem to be able to use that parameter.

I have been able to get it to a point where parse_xml can alert(param) and give [object object] which I would of thought meant that the object literal had been passed through, but when I try and call alert(param.xpos) I get undefined.

I know this is a pig of a problem, and I could get around it by just having the function take a zillion boolean parameters, but its just not a very nice solution.


In effect, what you have is this:

var params = {param: "value"};
foo("bar('one', 'two', 'three');");

...where foo uses eval on that string, something like:

function foo(codestring) {
    eval(codestring);
}

...and you're looking for how to embed params in that.

You could do this by serializing the object literal as a string so that when you combine it with the other string, and the total string is evaluated, it gets evaluated. Browsers are slowly getting JSON serialization built in, but for now you want to use jQuery, Prototype, or (if you just want this part) json2.js from Crockford, which offers JSON.stringify for turning objects that can be turned into JSON strings, into JSON strings. So:

var params = {param: "value"};
foo("bar(" + JSON.stringify(params) + ");");

But what you really want to do is refactor so that all of that logic is expressed as code, not code within a string. Then you could pass the literal directly, plus a whole raft of other benefits, including modularization, debugging, etc.

var params = {param: "value"};
function callBar() {
   bar(params);
}
foo(callBar);

...changing foo so that it calls a function rather than evaling a string. (eval is to be avoided whenever possible, and to paraphrase the Dalai Lama, it's [almost] always possible.) My sample foo changes to:

function foo(func) {
    func();
}

If foo needs to include additional information for bar (and if callBar is set up to handle those extra arguments), it can use Function#call or Function#apply to do that. (Those links are to MDC, but don't worry, they're not Firefox-specific, they've been in the ECMA spec for years and are nearly universally supported.)


You can't put an object inside a string. You would have to serialise the object, add it into the string, then parse it back into a structured object on the other side. The simplest way to do that would be to use JSON (via JSON.stringify or a library fallback for older browsers that don't have it), since JSON evaluates as simple JavaScript.

Note that you wouldn't get the exact same object back, but a new one with the same attributes and properties, and it only works for simple types, so you can't include a function in the object or anything.

However, in any case, passing JavaScript code around in strings is an anti-pattern to be strenuously avoided. Instead use inline functions, and you don't have to worry about what you can and can't put in a string, and you can get rid of all that unreadable wrapping and \-escaping:

var params = {xpos: 'false'};
on_change('window_3_cont_buffer', '', function() {
    var w= Window_manager.windows[3];
    var ps= w.window_cont_buffer.getElementsByTagName('content')[0].getElementsByTagName('p');
    if (ps[0].innerHTML==='ERROR') {
        alert(ps[1].innerHTML);
        return false;
    } else { 
        w.load_xml('location/view.php?location_ID=3', '', params);
    }
});


Some general techniques which may be helpful for you:

// Example of calling function objects given as arguments:

function on_change(foo, callback1, callback2) {
    if (foo)
        callback1();
    else
        callback2.call(available_as_this);
}

on_change(foo, function() { your code }, function() { another code });


// Example of function taking arbitrary number of arguments:

function any_params() {
    console.log('I got ' + arguments.length + 'arguments!');
    console.log('First argument: ' + arguments[0]);
}

any_params('one', 'two', 'three', [], null, {});

See arguments variable and call().


I want to use object literal to allow me to pass a random amount of variables in any order to a function.

Why oh why don't you just create an object which contains the parameters and functions, and pass that around? The receiving function can just test to see if a property of the object is set before trying to use it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜