[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/docs/flavor/ -> javascript_object_array.diviner (source)

   1  @title Javascript Object and Array
   2  @group javascript
   3  
   4  This document describes the behaviors of Object and Array in Javascript, and
   5  a specific approach to their use which produces basically reasonable language
   6  behavior.
   7  
   8  = Primitives =
   9  
  10  Javascript has two native datatype primitives, Object and Array. Both are
  11  classes, so you can use ##new## to instantiate new objects and arrays:
  12  
  13    COUNTEREXAMPLE
  14    var a = new Array();    //  Not preferred.
  15    var o = new Object();
  16  
  17  However, **you should prefer the shorthand notation** because it's more concise:
  18  
  19    lang=js
  20    var a = [];             // Preferred.
  21    var o = {};
  22  
  23  (A possible exception to this rule is if you want to use the allocation behavior
  24  of the Array constructor, but you almost certainly don't.)
  25  
  26  The language relationship between Object and Array is somewhat tricky. Object
  27  and Array are both classes, but "object" is also a primitive type. Object is
  28  //also// the base class of all classes.
  29  
  30    lang=js
  31    typeof Object;        // "function"
  32    typeof Array;         // "function"
  33    typeof {};            // "object"
  34    typeof [];            // "object"
  35  
  36    var a = [], o = {};
  37    o instanceof Object;  // true
  38    o instanceof Array;   // false
  39    a instanceof Object;  // true
  40    a instanceof Array;   // true
  41  
  42  
  43  = Objects are Maps, Arrays are Lists =
  44  
  45  PHP has a single ##array## datatype which behaves like as both map and a list,
  46  and a common mistake is to treat Javascript arrays (or objects) in the same way.
  47  **Don't do this.** It sort of works until it doesn't. Instead, learn how
  48  Javascript's native datatypes work and use them properly.
  49  
  50  In Javascript, you should think of Objects as maps ("dictionaries") and Arrays
  51  as lists ("vectors").
  52  
  53  You store keys-value pairs in a map, and store ordered values in a list. So,
  54  store key-value pairs in Objects.
  55  
  56    var o = {               //  Good, an object is a map.
  57      name: 'Hubert',
  58      species: 'zebra'
  59    };
  60  
  61   console.log(o.name);
  62  
  63  ...and store ordered values in Arrays.
  64  
  65    var a = [1, 2, 3];      //  Good, an array is a list.
  66    a.push(4);
  67  
  68  Don't store key-value pairs in Arrays and don't expect Objects to be ordered.
  69  
  70    COUNTEREXAMPLE
  71    var a = [];
  72    a['name'] = 'Hubert';   //  No! Don't do this!
  73  
  74  This technically works because Arrays are Objects and you think everything is
  75  fine and dandy, but it won't do what you want and will burn you.
  76  
  77  = Iterating over Maps and Lists =
  78  
  79  Iterate over a map like this:
  80  
  81    lang=js
  82    for (var k in object) {
  83      f(object[k]);
  84    }
  85  
  86  NOTE: There's some hasOwnProperty nonsense being omitted here, see below.
  87  
  88  Iterate over a list like this:
  89  
  90    lang=js
  91    for (var ii = 0; ii < list.length; ii++) {
  92      f(list[ii]);
  93    }
  94  
  95  NOTE: There's some sparse array nonsense being omitted here, see below.
  96  
  97  If you try to use ##for (var k in ...)## syntax to iterate over an Array, you'll
  98  pick up a  whole pile of keys you didn't intend to and it won't work. If you try
  99  to use ##for (var ii = 0; ...)## syntax to iterate over an Object, it won't work
 100  at all.
 101  
 102  If you consistently treat Arrays as lists and Objects as maps and use the
 103  corresponding iterators, everything will pretty much always work in a reasonable
 104  way.
 105  
 106  = hasOwnProperty() =
 107  
 108  An issue with this model is that if you write stuff to Object.prototype, it will
 109  show up every time you use enumeration ##for##:
 110  
 111    COUNTEREXAMPLE
 112    var o = {};
 113    Object.prototype.duck = "quack";
 114    for (var k in o) {
 115      console.log(o[k]); // Logs "quack"
 116    }
 117  
 118  There are two ways to avoid this:
 119  
 120    - test that ##k## exists on ##o## by calling ##o.hasOwnProperty(k)## in every
 121      single loop everywhere in your program and only use libraries which also do
 122      this and never forget to do it ever; or
 123    - don't write to Object.prototype.
 124  
 125  Of these, the first option is terrible garbage. Go with the second option.
 126  
 127  = Sparse Arrays =
 128  
 129  Another wrench in this mess is that Arrays aren't precisely like lists, because
 130  they do have indexes and may be sparse:
 131  
 132    var a = [];
 133    a[2] = 1;
 134    console.log(a);       // [undefined, undefined, 1]
 135  
 136  The correct way to deal with this is:
 137  
 138    for (var ii = 0; ii < list.length; ii++) {
 139     if (list[ii] == undefined) {
 140       continue;
 141     }
 142     f(list[ii]);
 143   }
 144  
 145  Avoid sparse arrays if possible.
 146  
 147  = Ordered Maps =
 148  
 149  If you need an ordered map, you need to have a map for key-value associations
 150  and a list for key order. Don't try to build an ordered map using one Object or
 151  one Array. This generally applies for other complicated datatypes, as well; you
 152  need to build them out of more than one primitive.


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1