Just JavaScript - In The Beginning Was The Object
Written by Ian Elliot   
Thursday, 13 March 2014
Article Index
Just JavaScript - In The Beginning Was The Object
Hoisting
Summary and Coming Next

Hoisting

There is one subtle difference between:

this.property=value;

and:

var property=value;

JavaScript implements hoisting to make it possible for you to use Global Properties before they have been declared. 

The rule is that every:

var property=value;

statement is first split into:

var property;
property=value;

and then the var part of the instruction is moved to the very top of the program. 

In other words, the declaration is moved to the top but the initialization is left in place. This means that the property exists from the moment the program runs but it isn't initialized until execution reaches the place in the program you intended it to be initialized. 

In most cases you can forget hoisting and just write:

var property=value;

where the initialization makes sense. 

Reference Semantics

It is important to realise that variables, i.e. properties of the Global object, store references to objects. This might seem to be a small matter but it changes the way assignment works. 

If you have a reference to an object and store it in another variable, for example:

var myObject1={};
var myObject2=myObject1;

then myObject2 references the same object as myObject1.

That is any changes you make to myObject1 will be made to myObject2 - they reference or point to the same object.

This is quite different to what happens in languages where variables store values. If a variable stores a value then assignment makes a copy of the value. 

Even in JavaScript assignment makes a copy - but it makes a copy of the reference to the object - not the object. 

Built In Objects - String

Now we have the use of the Global Object's properties we can create object that we can retain a reference to and use and modify later. For example:

this.myObject={};
this.myObject.newProperty={};

The problem is that because the only type of object we know about is the empty object this makes creating anything interesting difficult. 

JavaScript has a range of built-in objects which you can just use. 

How all this fits together will become clearer as we proceed but for the moment all you need to know is that there is a String object which can represent a string of character.

You can create a new string object initialized to a given set of characters using;

new String("characters")

So

new String("ABCD")

is a string object that represents ABCD i.e. its value is ABCD. 

There is a subtle point here. Notice that new String("ABCD") is a different object to new String("EFG"). A new object is manufactured each time we use new String.

Notice that if you know how things are actually implemented you will know that string are not implemented as full objects for reasons of efficiency. However how you should think about the high level aspects of a language is not the same thing as the messy details of its implementation. Strings are objects and they have methods and properties.

Using this we can now create an example of a custom object with some properties:

var myAddress= { Name:new String("John"),
                 Address:new String("A Town")
               }

This is an object with two properties Name and Address. You can guess that the idea is to use this object to represent a name and address. You can also see that we are using two String objects to as the objects associated with each property. 

You can retrieve the properties in the usual way.

For example

myAddress.Name

and

myAddress[Name]

both specify the String object - String("John").

Global Alert

The next problem we have is that we have no way of verifying that any of this actually works - currently you have to take it on trust. We can solve this problem with alert.

When JavaScript runs in a web browser the Global Object, i.e. window, has a number of properties but the one that is important to us is named alert. It can be used to display the value of any object that you specify. The value of an object is a fairly obvious representation of the object in as readable text.

The idea of the value of an object is something we will have to return to later because it is a more sophisticated an idea than you might think and it is very useful.

So for example:

window.alert({});

displays the text

object:Object

which isn't particularly useful but simply means that the object in question is a basic Object and not some other special built in object. If you try the same thing with a String object then you will see the text that it represents. For example

window.alert(new String("ABCD"));

displays the text ABCD.

There are two simplifications we can make to the code. The first is that as window is the global object we can write:

this.alert(new String("ABCD"));

or just

alert(new String("ABCD"));

The second is that the String object is so important that you can just write "ABCD" to create a String object with the value "ABCD".

So our display instruction can be reduced to:

alert("ABCD");

Which is probably the form you already know how to use. Such syntactic simplifications are useful but they tend to hide the principles of operation of JavaScript. 

If you know how strings are represented you will know that "ABCD" does differ from new String("ABCD"). The literal string "ABCD" is represented as a primitive string for efficiency reasons but JavaScript will pretend that it is an object any time it has to - see the section Primitive Problems.

Built-In Objects - Number

As you would guess just as there is a String object there is a Number object. 

If you try:

alert(Number(3));

you will see the number 3 displayed. You have created a Number object with the value 3.

JavaScript doesn't distinguish between different types of number - so no ints and floats. You can use integers, whole numbers, or decimal numbers such as 1.234 as values for Number objects.

This has implication that we have to look at later but for now you can just accept the simplification of not having to worry about different representations of numeric values.  

In theory JavaScript would not make a fuss about any form of representation of data. JavaScript does treat the Number 1 and the String "1" as being very similar and in many cases  they can be used interchangeably. This too can cause problems, but again it is an initial simplification. 

You can dynamically create properties and methods on Number objects as you can on any object.

For example:

var myObject=new Number(3);
myObject.myProperty="My Age";
alert(myObject.myProperty);

will display "My Age".

Of course, you don't have to write new Number() to create a Number object you can simply write its value, as in:

var myObject=3;

Now here we hit a snag - primitives.

The Primitive Problem

The idea that everything in JavaScript is an object is an ideal - and one not quite lived up to.

For efficiency reasons when you make use of a Number literal like 3 JavaScript doesn't create a Number object. It stores the 3 as a primitive data value. 

The same is true of String literals like "ABC" and of boolean, null and undefined - all of which will be described later. What matters at the moment is that idea that there are types of data that are not stored as objects for efficiency reasons. 

That is

var myObject=3;

actually creates a primitive value and not an object. 

However JavaScript does its best to pretend that myObject is a Number object. 

If you try to make use of a property of the Number object like

myObject.toString()

then JavaScript will oblige and convert the primitive value to a Number object and call the method

This automatic conversion is called boxing and the problem is that for efficiency JavaScript immediately unboxes a primitive value. This doesn't matter when you are trying to make use of built in properties but if you try to add a property it will be immediately lost. 

If you want to make use of custom properties on numbers you have to explicit box the value using the Number constructor as in the examples given earlier. 

In practice this doen't have any real impact on what you want to write because you don't often want or need to add custom properties to the built in objects. 

To be clear:

  • JavaScript's primitive data types behave like objects that you cannot add properties to - that is they cannot be customized. 
  • If you create the data type using say new Number then you get a complete object that you can use and customize. 

There is also an interesting extra problem in that if you try to use a property on a numeric literal using the "dot" notation - it doesn't work. The reason is that JavaScript interprets the dot as a decimal point. So you have to write not

3.toString();

but

(3).toString();

or

3["toString"];

 

Expressions and Immutability

One of the main tools of any programming language is the expression.

An expression takes data and combines it to produces new data.

For example, an arithmetic expression takes numbers and combines them to make new numbers. The ways in which the data can be combined takes the form of different operators. So arithmetic expressions have the addition operator and multiplication and so on. 

For example:

2+3*4

is an expression that combines 2, 3 and 4 and produces a new value of 14. 

When you think of expression in JavaScript you are encouraged to think of the operators as working with objects to create new objects.

For example:

2+3*4

combines three Number objects with values 2, 3 and 4 and creates a new Number object with the value 14.

In this sense you can imagine that the String and the Numeric objects are immutable - they don't change their values they are simply used to create new objects with different values.  

The fact that an expression always creates a new object is a natural idea that explains all sort of minor behavior in JavaScript. For example if you try:

var myObject=new Number(3);
myObject.myProperty="My Age";
var myObject2=myObject;
alert(myObject2);
alert(myObject2.myProperty);

You will find that myObject2 has a myProperty and its value is "My Age". This is because myObject2 refers to the same Number object myObject.

However if you make the small change to the code an add one to myObject as in: 

var myObject=new Number(3);
myObject.myProperty="My Age";
var one=new Number(1);
var myObject2=myObject+one;
alert(myObject2);
alert(myObject2.myProperty);

You will find that myObject2 has a value of 4 but it doesn't have a myProperty i.e. it is undefined.

The reason is that the arithmetic expression generates a new Number object that doesn't have a myProperty unless you go to the trouble of recreating it.

That is expressions that combine objects always create a new object.

Of course there is the complication of primitive data but in the main you can ignore it. The simple reason is that a primitive data value behaves as if it has only the default properties of the object and so when you combine them in an expression you get something that has just the default properties. Once again it looks as if expression take in objects and spit out a new object - even with primitive values. 

In short you can alway think of expressions as working with objects and creating a new object as the result. 

 



Last Updated ( Friday, 05 September 2014 )
 
 

   
RSS feed of all content
I Programmer - full contents
Copyright © 2014 i-programmer.info. All Rights Reserved.
Joomla! is Free Software released under the GNU/GPL License.