0

The following doesn't work (although it gives no explicit error), but why not?

And... Is there really no way around it, strictly using the with statement? Forget using for / foreach.

with (object1, object2) {
  attribute = value;
  method();
}

edit: Sorry to make 2 questions in 1. I'll try to make it clearer:

  1. Why the code above gives no syntax error, doesn't work but is accepted by with?

  2. If it's possible, how could we change multiple objects with same attribute using with?

Hopefully the following example will be more clear on what I wanted to accomplish:

var object1 = { attribute: 3 };
var object2 = { attribute: 2, method: function() { alert('blah'); } };
var object3 = { method: function() {alert('bleh'); } };

var value = 4;

with (object1) 
with (object2) 
with (object3) 
{
  attribute = value;
  method();
}

alert(object1.attribute + object2.attribute);

// resulting alerts should be, in order: blah, bleh, 8
Community
  • 1
  • 1
cregox
  • 17,674
  • 15
  • 85
  • 116

2 Answers2

6

Introducing multi-object scope with with

This is what I originally thought you were after, since you hadn't specified what your expected results were. Just stack the with statements:

var object1 = { attribute: 3 };
var object2 = { method: function() { alert('blah'); } };

var value = 4;

with (object1) 
with (object2) 
{
  attribute = value;
  method();
}

alert(object1.attribute);

Naturally, the object introduced by the inner-most with will override identically-named properties in any outer scope, including those of the outer with statements.

Standard disclaimers apply regarding performance hits and potential for errors caused by the use of with. Note that your example shows property access prefixed by . within the block, but this is incorrect - with modifies scope, temporarily putting an object at the front of the resolution chain, so no prefix is necessary (or allowed).


Targeting multiple objects

Regarding your edit: the comma operator lets you write something that appears to pass multiple expressions to with, but really only passes one of them. You're not going to be able to accomplish what you want without some sort of multicast delegate implementation (one that involves looping); JavaScript/ECMAScript don't have any built-in means of modifying multiple properties / calling multiple methods with a single assignment / call.

Quick 'n' dirty implementation:

function multicast()
{
  this.targets = Array.prototype.slice.call(arguments, 0);
}
multicast.prototype = {
  call: function(methodName)
  {
    var i;
    for (i=0; i<this.targets.length; ++i)
    {
      if ( this.targets[i][methodName] )
        this.targets[i][methodName].apply(this.targets[i],
          Array.prototype.slice.call(arguments, 1));
    }
  },
  set: function(propName, value)
  {
    var i;
    for (i=0; i<this.targets.length; ++i) 
      this.targets[i][propName] = value;
  }
};

Usage:

var object1 = { attribute: 3 };
var object2 = { attribute: 2, method: function() { alert('blah'); } };
var object3 = { method: function() {alert('bleh'); } };

var value = 4;

var delegate = new multicast(object1, object2, object3);
delegate.set('attribute', value);
delegate.call('method');

alert(object1.attribute + object2.attribute);
Shog9
  • 156,901
  • 35
  • 231
  • 235
  • That's pretty cool, but not it mostly makes me rephrase my question to what I originally meant... Please, try reading it again now! ;) – cregox May 02 '11 at 22:18
  • 1
    @Cawas: Hmm... The value of a good example that *specifies expected outputs* is proven yet again. I'm afraid you're in for some disappointment though - see my edit. You could probably come up with something a lot more clever using ECMAScript 5's getters/setters and a bit of pre-processing to generate method stubs, but the fundamental behavior will be the same. – Shog9 May 02 '11 at 22:45
  • That's perfect, Shog, thanks! Now I'm just wondering yet 2 more things: (1) Does ActionScript have such built-in means? Probably not, as well. (2) Were [ECMAscript a real dialect of LISP](http://stackoverflow.com/questions/5030285/is-ecmascript-really-a-dialect-of-lisp), could we make your implementation to replace `with`'s original built-in function? – cregox May 02 '11 at 22:51
  • @Cawas: I'm not aware of anything, but I don't work with ActionScript either. However, I rather doubt it - it would be a rather large extension to ECMAScript for something that can be trivially implemented in a library. – Shog9 May 02 '11 at 22:54
2

You can also use a reference to the object if you want to make your code shorter:

var o1 = object1
,   o2 = object2
;
o1.attribute = value;
o2.method();
Mathieu Rodic
  • 6,637
  • 2
  • 43
  • 49
  • Also cool, but not trying to make code shorter - just wondering about an alternate syntax statement. ;) – cregox May 02 '11 at 22:19