daemonl

In case you were wondering...

JS103 - Objects

In javascript, objects are just sets of key-value pairs. The keys can be numeric, like an array (0,1,2) or strings ('a', 'b', 'longer'), and their value can be any other object, string, number, function (which are all objects themselves).

Objects's values can be accessed and set in two different ways:

a.member = "m";  
  console.log(a.member); // "m"  
  console.log(a['member']); // "m"  

  a[0] = "zero";  
  console.log(a[0]); // "zero".  
  // But not a.0

a.member and a['member'] mean exactly the same thing. The only reason a.0 doesn't work is because 0 is a number and 'dot notation' doesn't work on numbers.

Just as a note for optimisation - the engines which run javascript in different browsers treat the two a little differently sometimes - the end result is always the same, but the behind-the-scenes memory use and speed can differ. e.g. in the V8 engine, which Google Chrome uses, an array 0, 1, 2, 3, 4 is stored differently to array 'a', 'str', 'somethingelse' - and as a result it confuses it a little doing 0, 2, 1000 or something like that. More details on that later, but the basic tip is use sequential numbers where it makes sense - like for lists of things, and strings where that makes more sense like for more 'object' like things.

When using either of those methods, the 'member' (read: key) you are accessing doesn't have to be set before you access it. That is, you can say a.something = "s" without first saying that a has a 'something'. Same for a['something']

What you DO need to do first is define that 'a' is an object, and this can be done in quite a few different ways.

var a = {};  
  a.something = "value";  

  // Shortcut:  
  var a = {  
    something: "value"  
  }

now {} is actually a shortcut for:

var a = new Object();  
  a.something = "value";  

  // And shortcut:  

  var a = new Object({something: "value"});

So var a = {...} is a shortcut for var a = new Object({...});. The things in the {} are the keys and values which will be assigned to the new object.

Recap:

var a = new Object({something: "value"});  
  // is the same as  
  var a = new Object();  
  a.something = "value";  
  // is the same as  
  var a = {something: "value"};  
  // and the same as  
  var a = {};  
  a.something = "value";  

  // and remember:  
  a['something']  
  // is just the same as a.something, so will be "value".

Next type - a little different, but the same pattern:

var a = [];  
  // is a shortcut for:  
  var a = new Array();  

  var a = ["a", "b", "c"];  
  // is a shortcut for:  
  var a = new Array("a", "b", "c");

We can so some funky things... which in the future you probably shouldn't do, but it's useful to know how it works:

var a = ["a", "b", "c"];  
  a.something = "value";  

  console.log(a[0]); // "a";  
  console.log(a.something); // "value"  
  // and of course:  
  console.log(a['something']); // "value"

What we've done here is add a property to a new object. Just like above. No problem, it's just that this one is an array, so it's expecting numeric keys in an order.

'But you said arrays were objects' and yes, indeed they are. They do everything an Object does, and they also do some more things specific to being an array, like sorting and such. So it's best to just leave them be as arrays, just for your own sanity

There's a special kind of value in every object (except for 'Object' itself) called it's proto or [[proto]] (depending on which browser or engine you ask). It's a private(ish) key, in chrome you can see it but don't change it. It's very useful to see the proto of an object to see what it's doing.

{}, or 'new Object()' created an object with one single key: 'proto'. Everything in the proto is in-build javascript functionality for objects, and is called 'Object' - which in turn has a proto which has the value of 'null'... null doesn't have a proto.

[], or 'new Array()' created an object with one single key: 'proto'. (Similar, hey?). It's proto contains in-built functionality for arrays, called 'Array'. 'Array' also has a prototype: 'Object'. So arrays do everything Objects do, and more.

How are the proto things actually used? when you use a.something, javascript will check the keys in 'a'. If it finds 'something', it will be returned, otherwise it will check a's proto for the function, then the proto's proto and so forth.

So that means that your new array '[]' doesn't need to have all of the functions javascript has for arrays, they can belong to the shared proto or all arrays called 'Array'.

Let's muck around with this feature a little:

Object.prototype.scareme = "Boo";  
  var a = "String";  
  console.log(a.scareme); // "Boo";

Totally. We just added a variable to ALL OBJECTS IN JAVASCRIPT!... (in our session)

Remember I said we can't write to the proto of an object? We can't, but we CAN write to the 'prototype' of the 'constructor' of the object - in this case, 'Object' is a constructor for all objects, and if it gets extra things on it's 'prototype', all other objects' proto will get that thing. I will explain that a little more in a post called 'new'

console.log(new String().__proto__);  

  String  
   - anchor: function anchor() { [native code] }  
   - big: function big() { [native code] }  
  etc etc.  

  var a = "small";  
  console.log(a.big()); // <big>small</big>

so our 'a' has no method 'big', but a's prototype (String) does, so it is called instead.

We can set our own methods (and properties, if we want... they are all the same) to our own existing objects, and to built in objects.

So what is an object then?

Remember from above: It's just a collection of keys and values. Just like an array. One of those keys just happens to be proto - which is just another array with it's own keys

var a = "";  
  console.log(a['big']); // function big() {...}  
  console.log(a.big); // function big() {...}  
  console.log(a['__proto__']); // String