views:

374

answers:

7

Is the following possible:

var someObject = {someProperty : "someValue"};
var someFunction = function() {
 someProperty = "anotherValue";
};

// what do I do here, in order to use
// someFunction to change someObject,
// without altering either of those things?

// directly accessing "someObject" in someFunction
// is not an option. e.g., none of this:
/*
   var someFunction = function() {
       someObject.someProperty = "anotherValue";
   };
*/

if(someObject.someProperty=="anotherValue") alert("Hooray!");

?

If not in regular JavaScript, is this possible in Mozilla's JavaScript for Firefox extensions?

Thanks.

A: 

No you can't.

var someFunction = function() {
    someProperty = "anotherValue";
};

Here someProperty is a global variable (created if not accessed before).

var someObject = {someProperty : "someValue"};

Here someProperty is a key of an object (not a variable).

So in each context the token someProperty refers to something different and completely independent.

There is no way for the function to alter the value of the object without a direct reference / calling another function to do it.

Johnco
I realize the difference between a key and a variable. Is this really not possible? I know the developers of Greasemonkey have done it somehow, but their source code is a mess.
Avindra Goolcharan
The best you can get without modifying your code more is @Phil Ross' reply, in which "this" is a reference to the object, but as I said, you allways need such a reference one way or the other.
Johnco
A: 
eval("someObject.someProperty='anotherValue'");

Will that work? What do you consider "directly accessing "someObject" in someFunction?" You're going to have to access someObject somehow if you want to change its property...

CrazyJugglerDrummer
By that, I mean literally typing "someObject." in someFunction. I want the code to work as it appears.
Avindra Goolcharan
A: 

If you are prepared to modify your function to reference this.someProperty instead of just someProperty, then you can use the apply or call:

var someFunction = function() {
  this.someProperty = "anotherValue";
};

someFunction.apply(someObject);
Phil Ross
I want to use something other than "apply". The idea is to be able to type code freely in the function without worrying about "this." or "someObject."
Avindra Goolcharan
A: 

No. This is all about scoping (environments) and properties.

When you say someObject = ... or someobject.whatever what you are saying is give me the someObject in the nearest scope and then do something with it.

Scopes nest. Functions create a new scope and capture the surrounding scope. Variables in closer scopes can shadow variables in surrounding scopes. Your function can see everything in the scope it was declared in, so it can see someObject.

someProperty is part of a key/value pair in someObject. Nothing cat get to it without going through someObject and asking it to retreive the value stored with the key someProperty.

z5h
Actually, someObject is in the scope of "window", as is every "global" object. The point is changing the main object from "window" to "someObject".
Avindra Goolcharan
A: 

For purely academic purpose, here's a way:

with (someObject) {
  eval('(' +someFunction.toString() + ')();');
}

Don't use this in production environment!

[Edit]: Just to clarify, here's how you use it.

var someObject = {someProperty : "someValue"};
var someFunction = function() {
 someProperty = "anotherValue";
};

with (someObject) {
  eval('(' +someFunction.toString() + ')();');
}

if(someObject.someProperty=="anotherValue") alert("Hooray!");

It DOES NOT refer to someObject inside someFunction.

Chetan Sastry
That refers to "someObject" inside the function body. The point is finding a way not to do this.
Avindra Goolcharan
Your question does not mention that. You say you can't modify either `someObject` or `someFunction` and you can't refer to `someObject` _inside_ `someFunction`. This approach does neither.
Chetan Sastry
I guess that does it, but it uses "with" and "eval", two of the last things anyone would want to use. I was hoping for some clever use of "apply" / "call" to allow this, but I guess it just isn't possible nicely.
Avindra Goolcharan
`apply/call` are for defining the context, not scope. So yeah, they're useless unless you want to refer `this`.
Chetan Sastry
+1  A: 

For those who may be wondering, the closest thing I've found is Components.utils.evalInSandbox. It's definitely not perfect, but easily the best thing for this problem.

Avindra Goolcharan
Of course any code you write using that isn't really portable JavaScript. I see on your profile you develop a lot of GreaseMonkey scripts, and so are probably accustomed to this behaviour. My recommendation is to move past your comfort zone and do things in a more generic JavaScript way. I would recommend much of Douglas Crockford's work as a source of knowledge/inspiration.That's just my 2 cents.
z5h
I personally have no need for writing in this way. I'm developing an add-on which would hugely benefit others who would write userscripts for it. As you can tell, this is the first time I'm really jumping into addon development. Don't put down us userscripters. We're not silly knuckleheads who don't know what we're doing. ;)As for portable: do you mean, as in, it could be used everywhere else? I'm a huge Firefox fan, and don't really care about it being used anywhere else. Sure Google Chrome is fast, but its super locked down and useless.
Avindra Goolcharan
I said that was my 2 cents because I wanted to be clear that I wasn't imposing my perspective too strongly. Having said that, everyone on this page says it can't be done. What they really mean is they don't think it's worth the trouble. If you really want, you can implement your own language in JavaScript with any semantics you want. Here's a parser/lexer generator for JS in JS to get you started. http://jscc.jmksf.com/
z5h
A: 
var someObject = {someProperty : "someValue"};
with (someObject)
{
  window.someFunction = function() {
   someProperty = "anotherValue";
  };
}

if(someObject.someProperty=="anotherValue") alert("Hooray!");

Not the best coding practice but should perform what you want.

BYK