WITH (this) {a;b;c}

Discussion in 'Javascript' started by SamJs, Nov 6, 2006.

  1. SamJs

    SamJs Guest

    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) ?
     
    SamJs, Nov 6, 2006
    #1
    1. Advertising

  2. SamJs

    VK Guest

    SamJs wrote:
    > 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.
     
    VK, Nov 6, 2006
    #2
    1. Advertising

  3. SamJs wrote:

    > 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
     
    Michael Winter, Nov 6, 2006
    #3
  4. SamJs

    RobG Guest

    Duncan Booth wrote:

    > "SamJs" <> wrote:

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

    >
    > 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.


    --
    Rob
     
    RobG, Nov 6, 2006
    #4
  5. SamJs

    VK Guest

    Duncan Booth wrote:
    > 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.

    > >>
    > >> 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.

    >
    > 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
     
    VK, Nov 7, 2006
    #5
  6. SamJs

    RobG Guest

    Duncan Booth wrote:
    > >> "SamJs" <> wrote:
    > >> > Is JavaScript explicit about the behavior of creating variables on a
    > >> > WITH (object) ?

    [...]
    > 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.


    --
    Rob
     
    RobG, Nov 7, 2006
    #6
  7. SamJs

    VK Guest

    VK wrote:
    > > Assignment never creates a new attribute on the object referred to in the
    > > 'with' statement.


    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...
     
    VK, Nov 7, 2006
    #7
  8. VK wrote:
    > VK wrote:
    >> Duncan Booth wrote:
    >>> 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.


    > 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.
     
    Richard Cornford, Nov 7, 2006
    #8
  9. SamJs

    VK Guest

    Richard Cornford wrote:
    > 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.
     
    VK, Nov 7, 2006
    #9
  10. VK wrote:
    > Richard Cornford wrote:
    >> 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"):


    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.
     
    Richard Cornford, Nov 7, 2006
    #10
  11. SamJs

    SamJs Guest

    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>
     
    SamJs, Nov 7, 2006
    #11
  12. In article <>, SamJs
    <> writes

    <snip>
    ><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
    --
    John Harris
     
    John G Harris, Nov 7, 2006
    #12
  13. SamJs

    Lich_Ray Guest

    In JavaScript1.5, with(object){
    field=xxx;
    }
    requare object.field has been created.
     
    Lich_Ray, Nov 9, 2006
    #13
  14. Lich_Ray wrote:
    > 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.
     
    Richard Cornford, Nov 9, 2006
    #14
  15. SamJs

    VK Guest

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



    Lich_Ray wrote:
    > 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 (?)
     
    VK, Nov 9, 2006
    #15
  16. 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
     
    Michael Winter, Nov 9, 2006
    #16
  17. SamJs

    VK Guest

    Michael Winter wrote:
    > 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.
     
    VK, Nov 9, 2006
    #17
  18. VK wrote:
    > Michael Winter wrote:
    >> 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

    <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.
     
    Richard Cornford, Nov 9, 2006
    #18
  19. SamJs

    VK Guest

    > > 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.
     
    VK, Nov 9, 2006
    #19
  20. VK wrote:
    >>> 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. ...

    <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.
     
    Richard Cornford, Nov 9, 2006
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.

Share This Page