WITH (this) {a;b;c}

S

SamJs

WITH (this) {
a = 5
}

I'm finding that this.a = 5 will come from this expression. I would
have thought that the search for a would come up undefined and leave it
at that.

Is JavaScript explicit about the behavior of creating variables on a
WITH (object) ?
 
V

VK

SamJs said:
Is JavaScript explicit about the behavior of creating variables on a
WITH (object) ?

That is irrelevant to with() construct. If you assign a value to a
non-existing object property, the engine creates new property first and
then assign to it.
 
M

Michael Winter

SamJs said:
WITH (this) {
a = 5
}

I'm finding that this.a = 5 will come from this expression.

Syntax error aside, that observation depends on the value of the this
operator. The this operator may, and often does, refer to the global object.

As long as there is no variable, a, within the scope chain, the
assignment expression above will create a new property on the global
object. If the this operator does indeed refer to that object, then the
expression

this.a

will evaluate to the number 5.

Compare to:

var object = {
method : function() {
with (this) {
a = 5;
}
alert(this.a);
}
};

object.method();

Here, the this operator refers to the object assigned to the variable,
object. As before, the assignment expression within the with statement
creates a property on the global object, but because the this operator
value is different, the expression evaluates to undefined.

[snip]
Is JavaScript explicit about the behavior of creating variables on a
WITH (object) ?

Yes: it never happens. Only existing properties can be read or assigned.

Mike
 
R

RobG

Duncan said:
Try this and you will find that assigning to 'a' doesn't create an
attribute on this:

Yes it does...
f = function() {
with(this) {
a = 42;
}
}
var g = new f();
alert("g.a:"+g.a+", window.a:"+window.a);
// displays: g.a:undefined, window.a:42

Because the value of this was the window object, so an a property was
added to window and assigned a value of 42.

but the following code will update the attribute on 'this':

window.a = undefined;
f = function() {
this.a = 'hello';
with(this) {
a = 42;
}
}
var g = new f();
alert("g.a:"+g.a+", window.a:"+window.a);
// displays: g.a:42, window.a:undefined

Because when you call f as a constructor, its this value is set to the
newly created object: this.<propertyName> assigns properties to the new
object.
 
V

VK

Duncan said:
Assignment never creates a new attribute on the object referred to in the
'with' statement.

Welcome to JavaScript :) and you are wrong as it's already pointed out
:-(
If property doesn't exist yet, it will be conveniently created for you.
Hello? Did you read the code?

It seems that you (as well as OP) are semi-mesmerized by with()
construct so presuming some hidden magic out of it: while it's nothing
but a shortcut tool.
with (this) {a = 'foo';}
programmatically is absolutely the same as
this.a = 'foo';

Try this:

function f() {
this.a = foo;
}

f();
alert(window.a); // 'foo'
var foo = new f();
alert(foo.a) // 'foo'

1] If property doesn't exist yet, it will be created during the
assignment.
2] The call context is everything in JavaScript
 
R

RobG

Duncan said:
[...]
Assignment never creates a new attribute on the object referred to in the
'with' statement.

So Mike said - maybe I should have believed him. :)

[...]
Did you read the code?

Yes, but it didn't sink in at the time. I don't use with, and probably
never will - thanks to this discussion I have a better idea of how it
works.
 
V

VK

Humply swallow my words back

<script>
function f() {
with(this) {
a = 'foo';
}
}

f();
alert(window.a); // foo
var foo = new f();
alert(foo.a); // undefined
</script>

Interesting...
 
R

Richard Cornford

Welcome to JavaScript :) and you are wrong as it's already pointed
out :-(
If property doesn't exist yet, it will be conveniently created for you.
Humply swallow my words back

<script>
function f() {
with(this) {
a = 'foo';
}
}

f();
alert(window.a); // foo
var foo = new f();
alert(foo.a); // undefined
</script>

Interesting...

As you have never managed to grasp the difference between scope chain
Identifier resolution and property accessor resolution you may find
seeing the expected result "interesting". In reality all you are doing
is again demonstrating that your ignorance of javascript, and fictional
perceptions of it lead you to repeatedly making false statements about
javascript, and wasting everyone's time reading them and correcting the
more coherent ones.

Richard.
 
V

VK

Richard said:
As you have never managed to grasp the difference between scope chain
Identifier resolution and property accessor resolution you may find
seeing the expected result "interesting". In reality all you are doing
is again demonstrating that your ignorance of javascript, and fictional
perceptions of it lead you to repeatedly making false statements about
javascript, and wasting everyone's time reading them and correcting the
more coherent ones.

Richard, don't be so boring (and so well-predictable).
:)

It is interesting indeed because the expected result (with
"Activation/Zombification" stuff flushed out and with "expected" fill
free to replace if you want with "expected by totally ignorant
programmers like VK"): the result would be the scope chain studied for
an object having [a] property and if no one found then *come back* to
the default object and add such property into it. Thus with() should be
acting as what it is: a shortcut where
someObject.someOtherObject.someProperty = 'foo';
and
with (someObject.someOtherObject) {
someProperty = 'foo';
}
doing the same thing.

That hits back I guess to the badly implemented with() mechanics in
JavaScript and in the particular the lack of default object accessor
shortcut.
 
R

Richard Cornford

VK said:
Richard, don't be so boring (and so well-predictable).
:)

It is interesting indeed because the expected result (with
"Activation/Zombification" stuff flushed out and with "expected"
fill free to replace if you want with "expected by totally ignorant
programmers like VK"):

That is near gibberish. But "expected by people who don't understand
javascript" will do.
the result would be the scope chain studied for
an object having [a] property and if no one found then *come back* to
the default object

By "default object" I assume you are again referring to the object at
the top of the scope chain.

Why would you expect the scope chain resolution of an Identifier to
"come back" to the top of the scope chain in the context of a - with -
statement when it does not do so in any other context?
and add such property into it. Thus with() should be
acting as what it is: a shortcut

Who said it was a 'shortcut'?
where
someObject.someOtherObject.someProperty = 'foo';
and
with (someObject.someOtherObject) {
someProperty = 'foo';
}
doing the same thing.

That hits back I guess to the badly implemented with()
mechanics in JavaScript and

The - with - statement in javascript does what it does; adds an object
to the top of the scope chain. How - with - statements may work in
other languages has no baring on whether that is a good or bad
implementation. Understanding what a - with - statement does in
javascript, and how javascript works (particularly with regard to the
resolution of Identifiers, and assignment to Identifiers) explains the
behaviour of code in - with - statements.
in the particular the lack
of default object accessor shortcut.

Javascript has never provided direct access to objects on the scope
chain.

Richard.
 
S

SamJs

Thank you to everyone for the effort put into this thread. I have
reservations about responding at all after reading the words in some of
the posts, but it seems to me more important to provide some kind of
closure.

I was wrong in my observation in the initial post. I read this thread
- twice - and built my own test script (included below) both to confirm
the thread and as pennance for beginning the thread with an erronious
observation. On digging deeper, I found that the properties which I
thought were being created were in fact declared elsewhere.

JavaScript does not read or write to with(object) properties which do
not exist.

It is riskier to use with () (as opposed to an explicit reference) as
the scope chain will be explored if a property is not found.

The only point I disagree with is the point of with(obj) not resulting
in shorter code. Perhaps not for a one-line situation, but when
several lines of code are involved, with(obj) can not only reduce the
coding, but can make the code easier to read.

Here's my test script. The results change slightly and in an expected
manner if the function reference is preceeded with "new".

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"
/>
<title>Untitled Document</title>
</head>

<body>
<script type="text/javascript">
var a

var myObj = {
b: undefined,

myFunc: function(c) {
var d
with (this) {
a = "Mares eat oats."; // Should assign to Global variable a
b = "Does eat oats."; // Should assign to myObj.b (same as this.b)
unless "new function" is used
c = "Little lambs eat ivy."; // Should assign to parameter c
d = "A kidd'l lee divey two."; // Should assign to local variable d
e = "Wouldn't you?"; // Should create and assign to global variable
e
};
alert('this.a: ' + this.a); // undefined
alert('this.b: ' + this.b); // Does eat oats (undefined if new
function())
alert('this.c: ' + this.c); // undefined
alert('this.d: ' + this.d); // undefined
alert('this.e: ' + this.e); // undefined
return;
}
}

// Do it
myObj.myFunc('howdy dowdy');
alert('global.a: ' + (typeof a == "undefined" ? "undefined" : a)); //
Mares eat oats
alert('global.b: ' + (typeof b == "undefined" ? "undefined" : b)); //
undefined
alert('global.c: ' + (typeof c == "undefined" ? "undefined" : c)); //
undefined
alert('global.d: ' + (typeof d == "undefined" ? "undefined" : d)); //
undefined
alert('global.e: ' + (typeof e == "undefined" ? "undefined" : e)); //
Wouldn't you?

</script>
</body>
</html>
 
J

John G Harris

<script type="text/javascript">
var a

var myObj = {
b: undefined,

myFunc: function(c) {
var d
with (this) {
a = "Mares eat oats."; // Should assign to Global variable a
<snip>

But not if some maniac has given the Object prototype a property named
"a".

Write 100 times : "with is dangerous" :)

John
 
L

Lich_Ray

In JavaScript1.5, with(object){
field=xxx;
}
requare object.field has been created.
 
R

Richard Cornford

Lich_Ray said:
In JavaScript1.5, with(object){
field=xxx;
}
requare object.field has been created.

In what sense "require"? That code is syntactically correct and has well
defined and certain behaviour, even if any object referred to by -
object - has no - field - property. If the assignment is intended to
influence a property of the - object - object then it must have a -
filed - property, but that is true for all ECMAScript implementations,
not jsut JavaScript(tm) 1.5.

Richard.
 
V

VK

Lich_Ray said:
In JavaScript1.5, with(object){
field=xxx;
}
requare object.field has been created.


Lich_Ray said:
In JavaScript1.5, with(object){
field=xxx;
}
requare object.field has been created.

Alas you may want to study over your testcase. As it was pointed by
others
with(someObject) {
missingProperty = 'value';
}
missingProperty will never be created for someObject. Instead the
engine will go along the scope chain to never come back again. If no
object with ["missingProperty"] property found anywhere, at the end of
the scope chain will be Global object and the engine will create new
property for this object. In more conventional terms it means that new
global variable missingProperty will be created.
This way with() acts as some kind of highly weird "mode strict" clause
with non-predeclared properties disregarded for the involved object but
polluting the global space.
However old the tradition of this weirdness would be (I traced it back
to Netscape 4.5) it is totally unacceptable now with element ID's
accounted as global variables (IE and now Firefox in Quirk mode).
It may lead to the most obscure errors one can imagine. See for
example:

<html>
<head>
<title>Test</title>
<script type="text/javascript">

function Shipping(c) {
this.carrier = c || 'unknown';
this.package = new Object();
with(this.package) {
container = 'big';
}
}

function init() {
var delivery = new Shipping();
}

window.onload = init;
</script>
</head>
<body>
<div id="container">Content</div>
</body>
</html>

IE simply reports "Object doesn't support this property or method"
because global "container" is already taken by DIVElement and you
cannot assign string values to a DOM element reference.

I'm not exactly sure what a hey Firefox is doing: it seems like it
studies on parsing stage all left hand side identifiers inside with{}
blocks and pre-declares them as global ones (as if they had var
keyword). (Anyone having a better explanation please welcome).

The only reasonable solution of this mess as I see it is to implement
the algorithm I suggested before: study the scope chain, if no match
found anywhere than come back to the default object and create new
property for it.
I don't see how would it affect any legacy scripts as I doubt very
much anyone ever used with(someObject){} construct as a way to create
global variables (?)
 
M

Michael Winter

VK wrote:

[snip]
with(someObject) {
missingProperty = 'value';
}
missingProperty will never be created for someObject. Instead the
engine will go along the scope chain to never come back again.

Why can't you just say that the identifier cannot be resolved, that it
doesn't exist as a property of an object within the scope chain?

[snip]
This way with() acts as some kind of highly weird "mode strict"
clause with non-predeclared properties disregarded for the involved
object but polluting the global space.

What on Earth is that supposed to mean?

The with statement temporarily adds a new object to the top of the scope
chain. That's all.

[Assigning to variables created from id attribute values]
IE simply reports "Object doesn't support this property or method"
because global "container" is already taken by DIVElement and you
cannot assign string values to a DOM element reference.

Sorry? Did you manage to forget that this is a loosely-typed language?
One does not assign to references, one assigns to variables and
properties, and these may change type and value at any time. Attempting
to assign to a read-only property does not raise an exception; it is
ignored.
I'm not exactly sure what a hey Firefox is doing:

What I wrote above should make it obvious. The question should be: What
is Microsoft doing?
it seems like it studies on parsing stage all left hand side
identifiers inside with{} blocks and pre-declares them as global ones
(as if they had var keyword).

It's amazing how simple things just fly right over your head.

[snip]

Mike
 
V

VK

Michael said:
What I wrote above should make it obvious. The question should be: What
is Microsoft doing?

It doesn't allow to override global variables created for ID'ed
elements (treated as Const). The only known salvation is to predeclare
all variables in your code with var: such declarations take precedence
over "ID pollution". Crazy - but maybe not so bad for enforcing proper
programming style on developers :). At the same time catastrophic for
the lazy coders and the with(){} amateurs (in the sense "who likes
something").

Actually: where is in ECMAScript 3ed exactly spelled that in case
someObject.nonExistingProperty="foo" nonExistingProperty has to be
created (rather than throw error). I tried to find, but I cannot read
Books of ECMA more than 30sec in the row, I'm getting nuts :) The
exact section number would be appreciated.
 
R

Richard Cornford

VK said:
It doesn't allow to override global variables created for ID'ed
elements
<snip>

Global variables are not created for IDed element, named properties of
the global object are created instead. The distinction will be lost on
you but they do explain some of the behaviour observed. Particularly
the fact that a global variable cannot be created with the - ReadOnly -
attribute, but a host may create a property of an object with that
attribute.
Actually: where is in ECMAScript 3ed exactly spelled that in case
someObject.nonExistingProperty="foo" nonExistingProperty has
to be created (rather than throw error).

If the [[CanPut]] method of the object returns false then the property
must not be created, but no exceptions are thrown. You are typically
vague in your assertion but if your use of the name
"nonExistingProperty" implies that the object itself _and_ none of its
prototypes has an existing property with that name, _and_ the object is
a native ECMAScript object, then the property must be created on the
object.
I tried to find, but I cannot read
Books of ECMA more than 30sec in the row,
I'm getting nuts :)
Getting?

The exact section number would be appreciated.

ECMA 262, 3rd Ed. Sections 10.1.4, 11.2.1, 11.13.1, 8.7.1, 8.7.2,
8.6.2.2 and 8.6.2.3

Richard.
 
V

VK

The exact section number would be appreciated.
ECMA 262, 3rd Ed. Sections 10.1.4, 11.2.1, 11.13.1, 8.7.1, 8.7.2,
8.6.2.2 and 8.6.2.3

Wow, so many numbers and not a single hit.
Thanks the advansed text search exists:

4.2.1
Unlike class-based object languages, properties can be added to objects
dynamically by assigning values to them. That is, constructors are not
required to name or assign values to all or any of the constructed
object's properties.
 
R

Richard Cornford

VK said:
Wow, so many numbers and not a single hit.
Thanks the advansed text search exists:

4.2.1
Unlike class-based object languages, properties can be added to
objects dynamically by assigning values to them. ...
<snip>

There is an obvious distinction between "can be added to objects
dynamically by assigning values to them'" and 'must be added to objects
dynamically by the assignment of values to them'. Though I doubt you
would see that.

Richard.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,521
Members
44,995
Latest member
PinupduzSap

Latest Threads

Top