object.property). And because the properties can be objects themselves, properties can be nested several levels deep (e.g.
object.propertyLvl1.propertyLvl2.propertyLvl3). Numbers, Booleans, and strings are not objects, _but _they act like objects. By this, I mean that you can use the “dot notation” to access the properties from them, even though they do not technically have properties of their own (e.g.
2.toString()). This works because when you do this, the number is converted to a
Number object and then the property is pulled from that object. Strings are converted to
String objects and Booleans are converted to
Boolean objects. This is a feature that can confuse newcomers but be quite useful to keep the code terse and readable.
To start an object literal, you just throw a curly brace up. Once you’re inside you just need to create key-value pairs that are separated with a colon. Then, to add more pairs just add commas between them. Any value can be used, as I said before, including another object, just like this:
You can also add properties to an object later on like this:
object.newProperty = "whatever you want".
Literals aren’t the only way to create objects. They can also be created using the
object = new Object();.
Object is what you implicitly extend from any time you create a new object. It provides a few properties automatically, which can be helpful, but most of the time is more annoying than anything.
The way you create a “class” is simply by creating a function called a constructor. You name the function starting with a capital letter to signify that it’s a constructor and not a normal function (this is a convention, not a requirement). Inside of this constructor function, the keyword
this refers to the instance of the object. Take a look.
Now, when you say
new SomeObject() you’ll get a new object that has a property of
someProperty with a value of one. You can, of course, do more than just set properties in a constructor function. You can do whatever you would normally do in a function.
Properties don’t need to be set within the constructor though. In fact, it is best practice to use the prototype to set properties, especially if the properties are functions and the class will be extended. Here’s how we add properties to the prototype.
The prototype is just an object that holds all of the properties that every instance of the object will automatically have when it is created with the
new keyword. It is also where inherited methods are put. Let’s create a new class that extends
Now we can add our new methods on, or override inherited methods. Note that we can’t assign an object literal to the prototype anymore because it would wipe out the methods we’ve already set or inherited because the entire prototype object would then be set to the object literal, rather than being extended by it.
If you’re interested more in how that works, you should check out the API documentation on either of their websites.
Being able to dynamically add to a prototype at any time opens up some interesting possibilities: specifically for extending native classes, like
Boolean. Maybe you want to change how
toString function works. If you make a change to the prototype, every single instance of a Boolean object (or Boolean primitive) will have the changes baked in. All you have to do is this little bit of code right here:
DO NOT DO THIS. I know I just showed you how, so it should be OK to do it, right? Well, I only showed you it because if you didn’t learn it here, you’d learn it somewhere else where they tell you (naively) that it’s ok. Well if you use any third party code or if there’s any possibility that someone might take over maintaining the project in the future (or immediately) then you’ll probably break something because no one expects the behavior to be different.