Object References in VBScript (Variables and Values in VBScript, Part 3)By Bill Wilkinson
|Part 3 in a Three-Part Series|
|This article is the third part in a three-part series. Part 1 of this series, Variables and Values in VBScript, examined how VBScript treated scalar variables: Strings and primitive data types. The second part, Variables, Values, and Arrays, delved deeper under the covers and looks at how VBScript handles both single and multi-dimensional arrays. This third and final part examines object references and how VBScript handles copying objects and arrays!|
Understanding Object References
In the previous articles in this series (part one and part two) we looked at the basics of how variables and values are implemented in VBScript (and, with minor variations, in JScript) and of how VBScript represents and uses arrays. As noted in the previous articles, in VBScript, all variables are always of the same kind or type, a VARIANT (which is in turn an OLE-defined structure). And a VARIANT instance always occupies 16 bytes of memory but only uses what is needed. The first two bytes of the VARIANT always indicate what the other 14 bytes are holding, and different types of data use pre-defined portions of those 14 bytes.
Now, let's consider an object in VBScript. For example, whenever you run any of the following code you are creating an object.
The first three examples there even say so, explicitly. The last example shows that some methods on one kind of
object can return a new object themselves! "But wait a minute!" you cry, "How can 14 bytes hold an entire
ADODB.RecordSet object or an entire
Scripting.Dictionary object?" Time to go back and
re-read part one of this series. To quote: "For all except the primitive
data types ... the VARIANT contains a pointer to the actual data!"
So all those variables above actually contain pointers to the various objects.
Okay, so what happens when you copy one of those variables to another variable? Perhaps a short demonstration is in order:
If you do that, you will see, as output:
from d1('second') we get: this via d2.add from d2('first') we get: added via d1.add
Hopefully, you understand that this is pretty clear evidence that both
d2 refer to exactly the same object! Changes made by either variable affect the
object that is referenced by either variable. Once again, it is important to understand that a variable that you
might think of as being an object is actually just a reference to an object. This is not strange. Other
computer languages have the same constructs. Java, for example, also allows only references to objects. And
C++ normally works with pointers and references to objects (though you can work directly with a
automatic object in that somewhat strange and wonderful language).
A Limitation of VBScript (and ActiveX) Objects
Simply put, the one thing you can not do with objects is copy them! Oh, there are a handful of ActiveX objects that have
clone methods available, but those are special cases, implemented
copy an object.
Actually, this makes sense. Let's consider a
Scripting.File object, for example. You use such an
object, say, to open a given file in exclusive mode, so only you can write to it. If you copied that object,
then what could happen in any reasonable way? You certainly couldn't have two objects such that each thinks it
has exclusive control of the same file! So VBScript (and ActiveX) simply doesn't implement any default copy or
clone operation. (The default in other languages, such as C++, is to simply copy the bytes in the object without
paying attention to context. Which is why most C++ programmers are forced to write "copy constructors" for all
but the simplest classes.) So it's pretty tempting to say that this VBScript "limitation" is actually a feature!
In Part 2 we'll examine how VBScript works with copying arrays.