views:

280

answers:

4

I am trying to define a function which can access variables which are in the scope of the function that is calling it.

( I am attempting to build a string formatter that is prettier than "a" + b, and more terse than String.format("a{0}",b). So I can get SF("a{b}"), and I don't know if it is possible )

so

function magic(str) {
    return parentScope[str]; // or return eval( str );
    // or something like that
}

function call() {
    var a = 1;
    alert( magic( "a" ) );
}
call();

would alert "1".

currently I can do this by having the function return code to be eval'd, but it seems like there must be a better way.

+1  A: 

Just put your 'magic' function into the call function:

function call() {
    function magic(str) {
        return a; 
    }

    var a = 1;
    alert( magic() );
}
call();

This mechanism behind the scenes is called closures and which are very powerful concept. Just think of an AJAX request where the callback function still can access the local variables of the calling function.

UPDATE

I misunderstood your question. The thing you actually want to build is impossible to implement in JavaScript because the is no way to access the caller's scope.

UPDATE 2

Here is my string formatting function. Not as concise as you may want it, but still very usable.

String.prototype.arg = function()
{
    result = this;

    // This depends on mootools, a normal for loop would do the job, too  
    $A(arguments).each((function(arg) 
    {
     result = result.replace("%", arg);
    }).bind(this));

    return result;
}

You can use it like:

"%-% %".arg(1,2).arg(3)

and receive

"1-2 3"
sebasgo
I don't think this helps given the context of the question - he's looking to pull arbitrary variable names out of a string based on formatting.
annakata
A: 

This might help.

http://www.prototypejs.org/api/function/bind

A: 

As far as I know it is impossible to reach out and grab an arbitrary variable from a function in javascript. From an object yes, but not from an executing method.

I can't think of any function method (apply, call, otherwise) which helps you here: frankly I think you're trying too hard for a marginal benefit over the normal string.format, er... format.

annakata
A: 

@sebasgo is correct, you can't do exactly what you're trying to do. But I thought you might like to see Prototype's String.interpolate method:

"#{animals} on a #{transport}".interpolate({ animals: "Pigs", transport: "Surfboard" });
//-> "Pigs on a Surfboard"

var syntax = /(^|.|\r|\n)(\<%=\s*(\w+)\s*%\>)/; //matches symbols like '<%= field %>'
var html = '<div>Name: <b><%= name %></b>, Age: <b><%=age%></b></div>';
html.interpolate({ name: 'John Smith', age: 26 }, syntax);
// -> <div>Name: <b>John Smith</b>, Age: <b>26</b></div>
Josh