// Literals, member access and bracket access agree var s = {name: "Ann", age: 30, "quoted key": true}; assert(s.name == "Ann"); assert(s["name"] == "Ann"); assert(s.age == 30); assert(s["quoted key"] == true); var dynamic = "age"; assert(s[dynamic] == 30); assert(tostr({}) == "{}"); // Missing keys are undefined assert(isundefined(s.nothing)); assert(isundefined(s["nothing"])); assert(isundefined({}.x)); // Writing existing and new keys s.age = 31; assert(s.age == 31); s.city = "Paris"; assert(s.city == "Paris"); s["country"] = "FR"; assert(s.country == "FR"); assert(s.name == "Ann"); // Every key can change to a value of any type s.name = 5; assert(s.name == 5); s.name = true; assert(s.name == true); s.name = null; assert(isnull(s.name)); s.name = [1, "two", {three: 3}]; assert(s.name[2].three == 3); s.name = "text again"; assert(s.name == "text again"); s.name = undefined; assert(isundefined(s.name)); s.name = function() { return "called"; }; assert(s.name() == "called"); // Different keys hold different types at once var mixed = { n: 1, s: "two", b: true, z: null, a: [1, "x", false], o: {inner: {deep: "yes"}}, f: function(x) { return x + 1; } }; assert(mixed.n == 1); assert(mixed.s == "two"); assert(mixed.b == true); assert(isnull(mixed.z)); assert(mixed.a[1] == "x"); assert(mixed.o.inner.deep == "yes"); assert(mixed.f(1) == 2); assert(mixed["o"]["inner"]["deep"] == "yes"); // Nested writes mixed.o.inner.deep = 42; assert(mixed.o.inner.deep == 42); mixed.a[0] = "now text"; assert(mixed.a[0] == "now text"); mixed.o.extra = [1, 2]; push(mixed.o.extra, 3); assert(len(mixed.o.extra) == 3); // Structs are shared, deepclone is not var alias = mixed; alias.n = 100; assert(mixed.n == 100); var copy = deepclone(mixed); copy.o.inner.deep = "copied"; assert(mixed.o.inner.deep == 42); copy.n = -1; assert(mixed.n == 100); // Structs in arrays and arrays in structs var people = [{n: "a", tags: ["x"]}, {n: "b", tags: []}]; push(people[1].tags, "y"); assert(people[1].tags[0] == "y"); people[0].n = 7; assert(people[0].n == 7); var names = []; foreach(var p : people) push(names, p.n); assert(names[1] == "b"); // Keys are compared by text var key = "a" + "b"; var t = {ab: 1}; assert(t[key] == 1); t[key] = 2; assert(t.ab == 2); t["a" + "c"] = 3; assert(t.ac == 3); // The most keys a struct holds var wide = {}; for(var i = 0; i < 16; i++) wide["k" + i] = i; for(var j = 0; j < 16; j++) assert(wide["k" + j] == j); wide.k3 = "overwritten without adding"; assert(wide.k3 == "overwritten without adding"); // Counters in a struct var counts = {hits: 0}; for(var h = 0; h < 5; h++) counts.hits++; assert(counts.hits == 5); counts.hits += 10; assert(counts.hits == 15);