JS Dictionaries, Objects and Lists - ThePix/QuestJS GitHub Wiki

Lists (also called arrays), dictionaries and objects are all ways to collecting data together. In a list, the data has an order, and each element is associated with a number. In a dictionary or object, each element is associated with a key, usually a string, and has no particular order. In an object, the data is associated with a class.

Dictionaries

A dictionary is a collection of name-value pairs. That is to say, it is a set of data in which each element of the data has a name to identify it and that can be used to access it, and a value.

If you want to store details about a person, you might want to record the persons age. You could use "age" as the name, and the actual age, the number, as the value.

The name is also known as the key.

Use curly braces to create a dictionary. You need to prove the key, followed by a colon, and then the data. Each name-value pair is separated by a comma. You can (and I recommend you always) have a comma after the last element.

const myDictionary = {
  age:16,
  bestFriend:'Lara',
  boyfriend:'Kyle',
}

The key can be anything, but if it is a single word, you do not need quotes (specifically, it has to start with letter or underscore, and contain only letters, underscores and digits). This example below shows that you can include spaces, but you need quotes in that case, and you can use numbers too. Generally I would advise against doing that.

const myOtherDictionary = {
  'best friend':'Lara',
  boyfriend:'Kyle',
  2:'Buddy',
}

You can access using square brackets for the index.

msg(myOtherDictionary['boyfriend'])
msg(myOtherDictionary[2])

myOtherDictionary[2] = 'Piggy Sue'

Behind the scenes all keys are converted to strings, by the way. This would have done the same as the last line in the previous.

myOtherDictionary['2'] = 'Piggy Sue'

Additionally, you can use the dot operator - but only if the key is a single word.

msg(myOtherDictionary.boyfriend)

myOtherDictionary.boyfriend = 'Buddy'

You can assign any value you like to it. I have just been assign strings above, but you can assign numbers, functions, other lists and other dictionaries.

There is a short-cut you can use when assigning functions. This example shows both approaches.

const myThirdDictionary = {
  getBestFriend:function() { return 'Lara' },
  getBoyFriend() { return 'Kyle' },
}

Objects vs dictionaries

In Javascript these are the same thing. If you do typeof for the dictionaries we created earlier, JavaScript will tell you they are objects.

In most languages objects and dictionaries are distinct, if related, data structures. Objects belong to classes, and the class gives the object its properties and behaviour. In interactive fiction, a program might have a class for garments, for example, and a hat would be an object of that class.

JavaScript works differently; behind the scenes the class is a dictionary, and so is the object, and they are linked by the "proto" attribute of the object. When we try to access an attribute of the hat, JavaScript looks it up as it would a dictionary, and if the hat itself has no attribute of that name, it will look for it in the prototype.

Note: This is just for illustration and is not how QuestJS actually works!

Lists vs dictionaries

In JavaScript these are the same thing. If you do typeof for a list, JavaScript will tell you it is an object too, just like the dictionaries.

So what is the difference between these things?

Lists are actually just dictionaries (or objects) with some special properties that allow them to be used differently.

Use square brackets to create a list. JavaScript will assign each element a number, starting from zero.

const myList = [
  'Lara',
  'Kyle',
  'Buddy',
]

The string "Lara" will get assigned to zero, "Kyle" to one, etc. You can access using square brackets for the index, just as we did for dictionaries.

msg(myList[0])

myList[2] = 'Piggy Sue'

You can add whatever keys you like to a list, just as you can a dictionary.

const myList = [
  'Lara',
  'Kyle',
  'Buddy',
]
myList[-1] = 'Fred'
myList[2.2] = ''Piggy Sue'
myList['boyfriend'] = 'Curly'

msg(myList.boyfriend)

Lists have a "length" property - the length of the list. This will only consider entries that assigned to natural numbers, 0, 1 and 2 in the example above, so "length" will be 3. In fact, it returns one more than the highest assigned value. In the example below, seven is the highest natural number key, so it will tell you the length is eight (and there are four empty elements).

const myList = [
  'Lara',
  'Kyle',
  'Buddy',
]
myList[7] = 'Fred'

msg(myList.length)

Having said all that, I would suggest never assigning anything to a list that is not a natural number or is outside the existing range. In fact, it is extremely rare you should need to use anything other than "unshift" or "push" to add anything to an existing list.

I said earlier that in a dictionary, the key is always converted to a string. Lists are dictionaries, and even in a list, the keys are converted to strings. In the example above, "Buddy" is associated with the string "2", not the number two.

If you need to determine if something is an array, use Array.isArray.

msg(Array.isArray(myList))

Functions vs dictionaries

In JavaScript these are the same thing! If you do typeof for a function, JavaScript will tell you it is a "function", and you can call functions, but you can also assign key-value pairs to a function just as you can for a dictionary.

Of course, functions have the additional property that they can be called.

Why would you want to do that? I do not know, but the possibility is there.

Classes

So what are classes and how do we use them?

A class is a way to define properties that we want several different objects to have. You can define them using a function, but I think it makes the intention clearer if you use the "class" keyword.

Here is a simple example. Note that you have to use the short-cut for functions. Two functions are defined. the "constructor" function has a special role as this will be called when a new Rectangle object is created.

class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }

  calcArea() {
    return this.height * this.width;
  }
}

r = new Rectangle(4, 3)

One the great things about classes that we can extend them to create new, more specialised ones. This is called inheritance; the extending class is said to inherit from the base class. In interactive fiction, you might have items as a class, extend that to have a class of items that can be picked up, and that in turn could be extended to create class of items that can also be worn (in fact QuestJS does not use classes, but in principle...).

This shows the idea, extending the above class. It uses the keyword "super" to refer to its parent class. This is required in the constructor - we have to call the constructor in the parent before doing pretty much anything here. It can also be used to access specific attributes.

class Square extends Rectangle {
  constructor(height) {
    super(height, height)
  }
}

s = new Square(3)