Setting fields on and object referenced by the 'with' statement
-
21-06-2021 - |
Question
In JavaScript, I simulate classes like this:
function MyClass() {} // Constructor
MyClass.prototype.myField = "foo";
I thought I'd make the code more readable and save keystrokes by using the with
keyword:
function MyClass() {} // Constructor
with (MyClass.prototype)
{
myField = "foo";
myOtherField = "bar";
myMethod = // etc
}
But if I then create an instance and try to access any of those fields, they're undefined
. However, if I do with (MyClass.prototype)
and then try to read values from it, that works - it's only when I try to change them or create new fields that it fails. I'm assuming this is because with (myObject)
scopes you to a clone of myObject, not an actual reference to the original instance.
So, is there any way to get around this? Any way to produce the results I want, with or with out with
? Or am I doomed to writing out MyClass.prototype
over and over again?
Solution
"if I then create an instance and try to access any of those fields, they're
undefined
"
You can't create new fields that way.
"if I do
with (MyClass.prototype)
and then try to read values from it, that works"
This is because you can read and update existing fields.
"I'm assuming this is because
with (myObject)
scopes you to a clone ofmyObject
, not an actual reference to the original instance. "
No, it's an actual reference to the object.
This sort of confusion is part of the reason why people avoid with
.
"So, is there any way to get around this? Any way to produce the results I want, with or with out with? Or am I doomed to writing out MyClass.prototype over and over again?"
Just use a variable.
var p = MyClass.prototype;
p.myField = "foo";
p.myOtherField = "bar";
p.myMethod = "etc";
You can also overwrite the existing prototype object, allowing object literal notation...
function MyClass() {}
MyClass.prototype = {
myField: "foo",
myOtherField: "bar",
myMethod: "etc"
};
You can also add a constructor: MyClass
if you want that.
OTHER TIPS
Have a look at this article which explains why you shouldn't use the with statement - the myField, myOtherField and myMethod variables will be created as global variables in your code because they don't already exist as properties of the prototype object.