Continuing the occasional series where I talk about writing JavaScript from a C# programmer's perspective.
This episode: the basics of objects in JavaScript.
If you'd read the previous episode of this series you'd have caught the fact that there is no class type in JavaScript, although — bizarre behavior warning — class
is actually a keyword (it's just not used). Since in C# the class is the template from which you can create objects, what exactly is an object in JavaScript?
The simple answer is that it's a named hash map. Riiight. What's a...
Imagine this using C#: you create a class with an indexer, the index type is string
, and the value is of type object:
public class JsObjectLookalike { private Dictionary<string, object> data = new Dictionary<string, object>(); public object this[string index] { get { return data[index]; } set { data[index] = value; } } }
It has no properties at all apart from the indexer, but you can create your own run-time properties as and when you wish. Here's an example of creating a person
object, with an age
property and a name
property:
var person = new JsObjectLookalike(); person["age"] = 42; person["name"] = "George";
The issue in C# is how to get the data out again. Usually, we'd have to deal with some ugly if
conditions and casts galore, which is why we don't tend to use this kind of design. Certainly if the types of the properties you want to define at run-time are all strings, say, then this design becomes a possibility. Luckily, when I use Console.WriteLine()
, this awkwardness gets temporarily hidden (ah, the magic of ToString()
...):
Console.WriteLine(person["age"]); // outputs 42 Console.WriteLine(person["name"]); // outputs George
So, in essence, a JavaScript object is a set of name/value pairs. The name is the key with which you get at the value, which can be any type at all. You can treat the name as an index in the same style as my C# code above, or, if the name is a valid identifier, by using the dot operator. Let's see how this is done.
First create an empty object:
var person = {};
In this case, JavaScript uses braces to define the property values for a new object, but here we're saying the object contains no properties (the bit between the braces is empty). Note that there's no new
in sight.
Let's add properties for age and name using the C# syntax above, and then read them back.
person["age"] = 42; person["name"] = "George"; console.log(person["age"]); // outputs 42 console.log(person["name"]); // outputs George
(Recall that I'm using Firebug in Firefox as my testbed. console.log()
is a function injected by Firebug to display data to the Console panel.)
I could have equally easily done this instead, since both age
and name
are valid identifiers:
person.age = 42; person.name = "George"; console.log(person.age); // outputs 42 console.log(person.name); // outputs George
I can also mix and match the ways which I access the properties, provided the property name is a valid identifier:
person["height"] = 1.82; console.log(person.height); // outputs 1.82
This shows that the same property is referenced whether I use the []
operator or the dot operator. Note, though that with the []
operator, the value in the square brackets can be any expression returning a string. (We'll use this ability to use a string expression below.) Take a look at this faintly weird example:
person[1] = "uh..."; console.log(person["1"]); // outputs uh...
Here what looks to be an array index, 1, is actually not. The number 1 gets coerced/converted at run-time into a string, "1"
, which is then used to name the property. You can't use the dot operator here, since 1 is not a legal identifier. (Hold that thought though for the next episode...)
You can create a fully populated object using a series of assignments to new properties as I've shown already, or you can use the JSON syntax:
var person = { age: 42, name: "George", height: 1.82, "is English": true };
In case you'd forgotten: JSON stands for JavaScript Object Notation. In this example, I've shown that you can declare property names either as standard identifiers or as quoted strings if the names are not valid identifiers. This type of object declaration is also known as an object literal.
You can also declare properties that are also objects themselves:
var person = { age: 42, name: "George", height: 1.82, salary: { currency: "$", amount: 75000 } };
And then can use the properties of those nested objects just as you'd imagine:
console.log(person.name + " earns " + person.salary.currency + person.salary.amount);
If you want to change a property value, just do it in the same manner you always use:
person.age = 31; person.name = "Joanna";
In fact, as you can see: there is no difference between creating a new property and setting its value, and modifying an existing property value. It's all the same. Unfortunately, this can really bite you if you manage to misspell the property name: you think you are setting an existing property, when in reality you are adding a brand new misspelled property. We'll talk about this in a future episode.
Not much more to say, really. Just like in C#, objects are reference types, not value types. They are accessed though a reference, and are passed around by reference.
Suppose we have the person
object with a salary
property as above. If we copy the salary
property and then modify it, we will be changing the original salary
too.
var georgeSalary = person.salary; georgeSalary.amount = 80000; console.log(person.salary.amount); // outputs 80000
We now know how to create an object and add properties to it (we'll look at methods in a later episode). But how do we know which properties an object has? After all, in C# this is well-defined: we just look at the object's class. An object is an instance of a class and we can't change that class at run-time. Duh, end of story. But, just like my original example above where we used a Dictionary<string, object>
and an indexer in order to be able to declare some run-time "properties", we can declare whatever properties we like for a JavaScript object.
JavaScript has a special for
loop that will enumerate the properties of an object. Actually, to be precise, it's a for..in
loop. It works like this:
var property; for (property in person) { console.log(property + ": " + person[property]); }
First I declare a variable, property
, and then I enumerate the properties in person
using the for..in
statement. In the body of the for..in
loop I merely output the property name and the property value using the []
operator. The result is this:
age: 42 name: George height: 1.82 salary: [object Object]
It seems a bit of a shame that for..in
can't be used in a C# foreach
sense. Oh well.
As we saw, adding a new property is easy, just reference it on the left hand side of an assignment. We can equally easily remove one using the delete
operator:
delete person.height;
Not much more can be said about that, apart from saying that delete
works on variables too, not just properties. It's a little weird from a C# viewpoint, but again think of the indexer and using it to create run-time properties.
The constructor function is Object
. The typeof
operator, applied to an object, returns the string value "object"
.
Next time we'll look at arrays, a special type of object.
Now playing:
Williams, Robbie - No Regrets
(from I've Been Expecting You)
3 Responses
#1 Dew Drop - February 10, 2009 | Alvin Ashcraft's Morning Dew said...
10-Feb-09 8:17 AMPingback from Dew Drop - February 10, 2009 | Alvin Ashcraft's Morning Dew
#2 Dew Drop - February 10, 2009 | Alvin Ashcraft's Morning Dew said...
10-Feb-09 8:17 AMPingback from Dew Drop - February 10, 2009 | Alvin Ashcraft's Morning Dew
#3 Sai Gudigundla said...
10-Feb-09 9:46 AMThese tutorials are very helpful. Keep 'em coming. You should write a book "Know C# ? then learn javascript"
Leave a response
Note: some MarkDown is allowed, but HTML is not. Expand to show what's available.
_emphasis_
**strong**
[text](url)
`IEnumerable`
* an item
1. an item
> Now is the time...
Preview of response