views:

235

answers:

6

Hi all, im trying for put a private var into an already existent function, example:

var AObject={
 get:function(s){
     return s.toLowerCase()+a;
    }    
}

function temp(){
    var a="A";
    var o={};
    eval("o.get="+AObject.get.toString());
    reurn o;
}

var bObject=temp();
BObject.get("B");    // "bA"
BObject.get();  /* error: s is undefined; but marked in line "return o;"
        and not in "return s.toLowerCase()+a;"*/

My target is to run get() function, owned by an existent AObject, with private var ... Im obtain it using eval(or new Function), but unfortunly the debugger will be broke!

So, there is a way to achieve this without using eval, or a way to use eval and keep debugger useful?

A: 

I think using an eval is your only option, if you want the local variable a to be usable inside the cloned function. Also, I would try a different debugger (Firebug on Firefox?)

Ates Goral
Yes, im using firebug, and the error is marked in a wrong line.
+1  A: 

The reason the debugger doesn't point to the line in the function, is that the function you are calling is not related at all (as far as JavaScript is concerned) to the AObject.get function. Eval has no way of knowing where the string defining the function came from. The debugger should be pointing to the line where you call eval, because that's where the function is defined, but it's apparently off by a line.

To answer your question, I don't think there's a way to avoid eval (or Function, which would probably be preferable) unless you can move the function definition inside temp so it closes over "a" or add an "a" parameter to the get function.

Matthew Crumley
A: 
function objectbuilder(a){
  return {
    get:function(s){
      return s.toLowerCase() + a;
    }
  };
}

function temp(){
  return objectBuilder("A");
}

var bObject=temp();
BObject.get("B");    // "bA"
BObject.get();
svinto
ehm... obvously i can't do in this way, the object already exists, or in plain terms, i have ti situation:temp({ get:function(s){ return s.toLowerCase() + a; } });
@blow: I don't understand what you mean.
svinto
A: 

@svinto

function temp(obj){
    var a="A";
    var o={};
    eval("o.get="+obj.get.toString());
    reurn o;
}

var myObj=temp({
    get:function(s){
     return s.toLowerCase()+a;
    }
});

myObject.get("B");   //bA

Are you understand now?

A: 

Are you trying to do something like this???

var AObject={
 get:function(s){
        return s.toLowerCase()+this.a;
    }    
}

function temp(){

    return {get:function(s){return AObject.get.call({a:"A"},s);}};

}

EDIT: after his comment;

do you know, what you would do is pretty wrong, it works only because eval change the scope chain, basically you're doing this:

function temp(obj){
    var a="A";
    var o={};

    o.get=function(s){
            return s.toLowerCase()+a;
    }

    return o;
}

since a is in a closure, this will work, but you're not calling the true obj get function, instead you're creating another one that work inside temp;

But, as I state in the comment, you shouldn't write function that contains undeclared variable, instead you should pass this variable at the function, as svinto does.

Edit: deleted wrong code.

kentaromiura
<a> must be a private variable, inacessible by this keyword.
Excuse me for the question, but Why?If you have a private var, you have to pass this var around, there's the only way or, depending of what you *really* want, another one is to apply/call a method on a object.
kentaromiura
Im looking for a way to build a class by passing an object as arguments; my class must own private members.Eval works good, except it broke debugger.
A: 

@kentaromiura

No, your way works only becouse you put variable in window scope (global...)

Your "this" key is the "window" object, so when you do

this.a="A"

is like do

window["a"]="A"

In this way become a global var

function temp(obj){
    var a="A";

    return (function(){
        this.a =a;
        var o={};    
        o.get=function(s){return obj.get.call(this,s)};    
        return o;
    })();

}

var myObject=temp({
    get:function(s){
        return s.toLowerCase()+a;
    }
});

alert(myObject.get("B"));   //bA
alert(a); //A

This is not a workaround, must be private, not global. If i decide to use global var im starting to use a global vector where i can store my private var. Thank you.

You're perfectly right, sorry ;)
kentaromiura
Why didn't you use public istance variable? It's always better than writing method with undeclared global ...
kentaromiura