creation
let day1 = {
squirrel: false,
events: ["work", "touched tree", "pizza", "running"]
};
properties
There are two main ways to access properties. With a dot value.x or brackets
value[x]. The difference is in how x is interpreted. When using a dot, the
work after the dot is the literal name of the property. When using brackets, the
expression between the brackets is evaluated to get the property name. So if you
know the property is named "color" you'd use value.color. If you wanted to
extract the property named by the value held in variable x you would use
value[x]. Property names are strings.
The elements in an array are stores as the array's properties, using numbers as
the property names. Because you cannot use the dot notation with numbers and
usually want to use a variable that holds the index anyway you must use bracket
notation. The length property of an array tells how many elements it has.
Typically, you'd write array.length, but array["length"] is technically
valid.
keys
Object.keys returns an array of an objects properties.
check for a property
Objects can have hidden properties brought in from their prototype. For more
information see js classes. The methods hasOwnProperty checks if an object
has it's own property as opposed to inheriting it. The in operator can be used
if you want to include inherited properties. Unfortunately, the hasOwnProperty
method can be overwritten so it's best to use the following:
let map = {one: true, two: true, hasOwnProperty: true};
// Fix this call
console.log(map.hasOwnProperty("one"));
assign
A function that copies all properties from one object to another. Does not replace existing properties so you can use this to add a set of new properties to an object.
delete a property
One subtlety is that deleting an object is different than setting it's value to
undefined. If the property exists, but is set to undefined, in will report
true.
let anObj = {left: 1, right: 2};
console.log(anObj.left);
// 1
delete anObj.left;
console.log(anObj.left);
// undefined
console.log("left" in anObj.left);
// false
console.log("right" in anObj.left);
// true
methods
Methods are nothing more than properties that hold function values. When a
function is called as a method; looked up as a property and immediately called,
as in object.method() the variable this in it's body automatically points to
the object that it was called on.
function speak(line) {
console.log(`The ${this.type} rabbit says '${line}'`)
}
let whiteRabbit = {type: "white", speak}
let hungryRabbit = {type: "hungry", speak}
whiteRabbit.speak("Oh my ears and whiskers, " +
"how late it's getting!")
hungryRabbit.speak("I could use a carrot right now.")
If you want to pass this explicitely (without needing to call the function
from an object) you can use .call:
speak.call(hungryRabbit, "Burp!")
Arrow functions are different. They do not bind their own this but can see the
this in the scope around them. So, you can reference the "outer" this inside
a local arrow function.
prototypes
In addition to their own set of properties, most objects also have a
prototype. A prototype is another object that is used as a fallback source of
properties. Then an object gets a request for a property it does not have, it's
prototype will be searched for the property, then the prototype's prototype, and
so on.
let empty = {};
console.log(empty.toString)
// function toString(){ ... }
console.log(empty.toString())
// [object Object]
An empty object uses the Object.prototype which is the root prototype behind
almost all objects. Functions derive from Function.prototype and arrays from
Array.prototype. Those prototypes themselves have the prototype of
Object.prototype:
console.log(Object.getPrototypeOf({}) == Object.prototype) // true
Additionally, you can create objects with a specific prototype. Using prototypes this way forms a rudimentary class system. Several newer language extensions exist make this a bit more ergonomic.