As the title says, it’s a bunch of notes and examples on the topic of Objects in Javascript that I have collected over the years. Some are my own and some are unashamedly borrowed from multiple resources on the internet, whose authors are simply too numerous to mention.
Inheritance and the prototype chain
When it comes to inheritance, JavaScript only has one construct: objects. Each object has a private property (referred to as [[Prototype]] ) which holds a link to another object called its prototype. That prototype object has a prototype of its own, and so on until an object is reached with null
as its prototype. By definition, null
has no prototype, and acts as the final link in this prototype chain.
Nearly all objects in JavaScript are instances of Object
which sits on the top of a prototype chain.
While this is often considered to be one of JavaScript’s weaknesses, the prototypal inheritance model is in fact more powerful than the classic model. It is, for example, fairly trivial to build a classic model on top of a prototypal model.
Inheritance with the prototype chain
Inheriting properties
JavaScript objects are dynamic “bags” of properties (referred to as own properties). JavaScript objects have a link to a prototype object. When trying to access a property of an object, the property will not only be sought on the object but on the prototype of the object, the prototype of the prototype, and so on until either a property with a matching name is found or the end of the prototype chain is reached.
Following the ECMAScript standard, the notation someObject.[[Prototype]]
is used to designate the prototype of someObject.
Since ECMAScript 2015, the [[Prototype]]
is accessed using the accessors Object.getPrototypeOf()
and Object.setPrototypeOf()
. This is equivalent to the JavaScript property __proto__
which is non-standard but de-facto implemented by many browsers.
It should not be confused with the func.prototype
property of functions, which instead specifies the [[Prototype]]
to be assigned to all instances of objects created by the given function when used as a constructor. The Object.prototype
property represents the Object
prototype object.
The Object.setPrototypeOf()
method sets the prototype (i.e., the internal [[Prototype]]
property) of a specified object to another object or null
.
Warning: Changing the [[Prototype]]
of an object is, by the nature of how modern JavaScript engines optimize property accesses, a very slow operation, in every browser and JavaScript engine. The effects on performance of altering inheritance are subtle and far-flung, and are not limited to simply the time spent in obj.__proto__ = ...
statement, but may extend to any code that has access to any object whose [[Prototype]]
has been altered. If you care about performance you should avoid setting the [[Prototype]]
of an object. Instead, create a new object with the desired [[Prototype]]
using Object.create()
.
Object.setPrototypeOf()
is in the ECMAScript 2015 specification. It is generally considered the proper way to set the prototype of an object, vs. the more controversial Object.prototype.__proto__
property.
JavaScript has a special keyword, this, that you can use within a method to refer to the current object.
Javascript supports OOP because it supports inheritance through prototyping as well as properties and methods.
Note that an object is just a special kind of data.
Objects contain one or more key-value pairs. The key portion can be any string. The value portion can be any type of value: a number, a string, an array, a function, or even another object.
[Definition: When one of these values is a function, it’s called a method of the object.] Otherwise, they are called properties.
As it turns out, nearly everything in JavaScript is an object — arrays, functions, numbers, even strings — and they all have properties and methods.
An object has properties and methods.
Note that methods are just functions attached to objects
Properties are variables created inside an object and methods are functions created inside an object.
In JavaScript you can define your own objects.
In addition, you can assign methods and properties to each object, pre-written or self-defined.
* Methods are ‘things that do something’, they can be recognized by their brackets (). When you call them, like object.method(), something happens.
* Properties are ‘things that are something’. They have a value, for instance a number, a string or a Boolean value. When you call them, like object.property, you get (or set) this value.
Normal JavaScript functions are also methods (hence the brackets).
document.write(‘text’) executes the pre-defined write() method of the document object.
If you write your own functions you add methods to the window object, the parent of all other JavaScript objects.
While using the new operator or literal notion to create a custom object is both simple and logical, the biggest shortcoming is that the result is NOT reusable- we cannot easily initialize different versions of the created object. For example with the first demonstration above, if the person’s name is not “Tim Scarfe”, we would need to redefine our entire object just to accommodate this change.
Whereas an array holds a list in a certain order, an object is an unordered collection.
Objects hold attributes that point to values.
A value could be one number or a single line of text.
Or, a value can be an array
Creating objects using new Object()
There are several ways to create objects in JavaScript, and all of them have their place. The simplest way is to use the new operator, specifically, new Object():
Below we define a custom object “person,” then add to it its own properties and method afterwards. In this case, the custom method merely initializes two more properties.
person = new Object()
person.name = “Tim Scarfe”
person.height = “6Ft”
person.run = function() {
this.state = “running”
this.speed = “4ms^-1”
}
OBJECT LITERAL
What is an object literal? In nontechnical terms, it is a means of containing a lot of data in one tidy package.
It is a comma separated list of name value pairs wrapped in curly braces.
Object literals are used as a means of encapsulating data, avoiding the use of global variables which can cause problems when combining code.
How and Why We Use Object Literals
Objects literals enable us to write code that supports lots of features yet still make it a relatively straightforward for the implementers of our code. No need to invoke constructors directly or maintain the correct order of arguments passed to functions, etc.
Object literals are also useful for unobtrusive event handling, as a way of holding data that would otherwise have been passed to functions called from HTML event handler attributes.
TIP. The literal notation of creating JavaScript objects has one weakness – it can only be used to describe objects. With other words, using the literal notation you can only define (key, value) pairs, but you can’t create classes, class constructors, or other reusable components of code.
Creating objects using Literal Notation
Another inline way of defining an object is via literal notation. Supported in JavaScript1.2 and above, it’s a more robust form of creating an object on the fly:
Literal notion can contain arrays or arbitrary JavaScript expressions or values.
Dot notation is faster to write and clearer to read.
Square bracket notation allows access to properties containing special characters and selection of properties using variables.
In JavaScript an object literal is declared or defined as follows:
var myObject = {}
An object literal with a few properties, from a Rotating Images example:
var myRotator = {
path: ‘images/’,
speed: 4500,
images: [“smile.gif”, “grim.gif”, “frown.gif”, “bomb.gif”]
}
// Object Literals
timObject = {
property1 : “Hello”,
property2 : “MmmMMm”,
property3 : [“mmm”, 2, 3, 6, “kkk”],
method1 : function(){alert(“Method had been called” + this.property1)}
};
timObject.method1();
alert(timObject.property3[2]) // will yield 3
Creating Objects
To demonstrate, let’s create a new object that has three properties; two store numeric values, while the other is an anonymous function (a function with no name):
var AnimationManager = {
framesPerSecond: 30,
totalLength: 15,
startAnimation: function(){ /* code goes here */ }
}
It’s important to note that the object literal is really just a shortcut to creating objects using JavaScript’s built-in Object type. We’ll explore the code in more detail later, but for now just remember that we could also create the AnimationManager object with the following:
var AnimationManager = new Object();
AnimationManager.framesPerSecond = 30;
AnimationManager.totalLength = 15;
AnimationManager.startAnimation = function () { /* code goes here */ };
JSON uses object literal notation. The form:
var person = {
“name”: “Douglas Adams”
“age”: 42
};
Is exactly the same (for all intents and purposes) as:
var person = new Object();
person.name = “Douglas Adams”;
person.age = 42;
Does that help you?
You can also use
person[“age”]
this is the same as
person.age
and to iterate through named properties:
//prints the person.propertyName for all propertyName in person
for (var propertyName in person) {
alert(person[propertyName]);
}
var o = {a:1, b:2, c:3};
function show_props(obj, objName) {
var result = “”;
for (var i in obj) {
result += objName + “.” + i + ” = ” + obj[i] + “\n”;
}
return result;
}
alert(show_props(o, “o”));
/* alerts :
o.a = 1
o.b = 2
o.c = 3
16.*/
Hash Tables – all 4 examples below are equivalent
var myHashtable = {}; // object literal ?
myHashtable[“name”] = “Carl”;
myHashtable.city = “Anytown”;
var myHashtable = {name : “Carl”, city : “Anytown”}; // object literal
var myHashtable = {“name” : “Carl”, “city” : “Anytown”}; // json
var myHashtable = new Object(); // object
myHashtable[“name”] = “Carl”;
myHashtable.city = “Anytown”;
Object Constructor
We need a way to create an object “type” that can be used multiple times without having to redefine the object every time to meet each particular instance’s needs. The standard way to achieve this is to use the Object Constructor function.
An object constructor is merely a regular JavaScript function, so it’s just as robust (ie: define parameters, call other functions etc). The difference between the two is that a constructor function is called via the new operator (which you’ll see below). By basing our object definition on the function syntax, we get its robustness as well.
function cat(name) {
05 this.name = name;
06 this.talk = function() {
07 alert( this.name + ” say meeow!” )
08 }
09 }
10
11 cat1 = new cat(“felix”)
12 cat1.talk() //alerts “felix says meeow!”
13
14 cat2 = new cat(“ginger”)
15 cat2.talk() //alerts “ginger says meeow!”
Here the function “cat()” is an object constructor, and its properties and methods are declared inside it by prefixing them with the keyword “this.” Objects defined using an object constructor are then instantiated using the new keyword. Notice how we’re able to easily define multiple instances of cat, each with its own name- that’s the flexibility object constructor brings to custom objects. Constructors create the blueprints for objects, not the object itself.
Adding methods to our object using prototype
We saw above how to add a method to our constructor function by merely declaring it inside the function. Another approach is through prototyping, which is also more popular due to its elegance. Prototype is a type of inheritance in JavaScript. We use it when we would like an object to inherit a method after it has been defined. Think of prototyping mentally as “attaching” a method to an object after it’s been defined, in which all object instances then instantly share.
Lets extend our original cat() object above with an additional method to change the cat’s name, using prototype:
cat.prototype.changeName = function(name) {
this.name = name;
}
firstCat = new cat(“pursur”)
firstCat.changeName(“Bill”)
firstCat.talk() //alerts “Bill says meeow!”
As you can see we merely use the keyword “prototype” immediately following the object’s name to utilize this functionality. The custom method changeName() is now shared by all instances of cat.
Prototyping works on both custom objects and select prebuilt objects, such as Date() or String. For the later, the general rule is that you can prototype any prebuilt object that’s initialized with the “new” keyword.
As we have seen, JavaScript supports prototype inheritance instead of class based. It’s possible for inheritance to happen other ways, however.
The following is an example of inheritance through functions.
function superClass() {
this.supertest = superTest; //attach method superTest
}
function subClass() {
this.inheritFrom = superClass;
this.inheritFrom();
this.subtest = subTest; //attach method subTest
}
function superTest() {
return “superTest”;
}
function subTest() {
return “subTest”;
}
var newClass = new subClass();
alert(newClass.subtest()); // yields “subTest”
alert(newClass.supertest()); // yields “superTest”
Prototype based inheritance is a far better bet for JavaScript applications in most cases.
The prototype object of JavaScript, introduced starting in JavaScript 1.1, is a prebuilt object that simplifies the process of adding custom properties/ methods to all instances of an object.
The prototype object is here to help when you wish to quickly add a custom property to an object that is reflected on all instances of it. To use this object, simply reference the keyword “prototype” on the object before adding the custom property to it, and this property is instantly attached to all instances of the object
There is an important thing to take note at this point in the tutorial. While you are free to use the prototype object on any custom objects, this is NOT the case with prebuilt ones (such as image, string etc). JavaScript only allows you to “prototype” prebuilt objects that are created with the new keyword, such as the following:
* The image object
* The string object
* The date object
* The Array object
Once we’ve defined an object function, we have to instantiate it to actually use it. Instantiating an object function means using the keyword “new” in front of the object name, and then creating an instance of the object by assigning it to a variable:
Function objects can be a little more useful than the object literals we just discussed, though, in that they can be used as a template for new objects.
For those unfamiliar with object-oriented programming, this object template is also known as a class. Instead of starting with a blank slate each time, objects built from a class are pre-populated with methods and properties. By defining a new function object, we are, in effect, defining a blueprint for new objects that we can use over and over again.