Creating objects
Creating a new object
There are four ways to create a new object:
- Using an object literal, aka object initializer
- Using a constructor function (with keyword
new
) - Using classes. Classes will be covered later this tutorial.
- Using the
Object.create
method
In the next example three empty objects are created.
const myObject1 = {}; // created via an object literal
const myObject2 = new Object(); // created via a constructor function
const myObject3 = Object.create(Object.prototype); // created via Object.create()
Object literals
With an object literal (aka object initializer) you can create the object and directly add properties to the object in one expression.
An object literal is an unordered, comma-delimited list of zero or more pairs of keys and values enclosed in curly braces ({}
).
const myObject = {
a: 1,
b: 2,
c: 3,
d: function() {}
}
As mentioned in the previous chapter, you may enclose keys in quotes, but common practice is to omit them, unless the key is not a valid identifier (except numbers): then quotation marks are required. Although not valid identifiers, number keys do not require quotation marks, in fact, common practice is to omit quotation marks, just like with valid identifiers.
You may need to wrap an object literal in parentheses if it appears where a statement is expected (object literal at the beginning of a statement).
This is because the {
will be interpreted as the beginning of a block statement.
Property shorthand
Object literals support a range of shorthand syntaxes for setting properties.
Assigning a variable value to a property, where variable identifier and property name are the same:
const foo = 1;
const bar = { foo: foo }
Shorthand:
const foo = 1;
const bar = { foo }
Shorthands and standard syntax can be combined. Also methods can be included using this shorthand.
const a = 'foo';
const b = 42;
const c = function() { return this.b };
function d() { return this.b };
o = { aA: a, b, c, d };
console.log(o.aA); // logs: "foo"
console.log(o.c()); // logs: 42
console.log(o.d()); // logs: 42
Method shorthand
Directly initializing a method in the object literal can be done with an other shorthand notation.
With this shorthand the keyword function
is no longer necessary.
const foo = { bar: function() {} }
Shorthand:
const foo = { bar() {} }
Computed property names
Object literals also support computed property names that allow expressions in square brackets []
.
This is reminiscent of the bracket notation for accessing properties.
This way we can add dynamic keys directly at declaration.
const myVariable = "foo";
const myObject = {
[myVariable]: "bar"
};
console.log(myObject.myVariable); // logs: undefined
console.log(myObject[myVariable]); // logs: "bar"
const myArray = ["A", true, 2];
const a = {
[myArray]: "Hello",
};
console.log(a["A,true,2"]); // logs: "Hello"
const x = 0;
const b = {
[`prop${(() => 2 + x)()}`]: 2 + x
};
console.log(b.prop2); // logs: 2
Constructor functions
An other way to create an object is via a constructor function. This requires these two steps:
- Define a constructor function. By convention, the name of the constructor function needs to have an upper-case first letter.
- Create an instance of the "object type", defined by the constructor function, by using keyword
new
.
Each created instance is an object on its own. You can add a property to one instance of an object type, but that does not affect any other instance of that object type. Adding properties, at run-time, to all objects of the same type via the constructor function is not possible.
// constructor function:
function User(name, avatar, nComments) {
this.name = name;
this.avatar = avatar;
this.nComments = nComments;
};
const user1 = new User('John Doe', 'John1986', 321);
const user2 = new User('Jane Roe', 'Marge Bouvier', 4022);
console.log(user1); // logs: { name: "John Doe", avatar: "John1986", nComments: 321 }
console.log(user2.avatar); // logs: "Marge Bouvier"
user2.gender = 'female';
console.log(user1.gender); // logs: undefined // "user1" does not have property "gender"
console.log(user2.gender); // logs: "female"
Keyword this
is used to define the object's properties. The assigned values are the arguments passed to the function.
Properties can have objects as value:
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
function Driver(name, age, car) {
this.name = name;
this.age = age;
this.car = car;
}
const fancyCar = new Car("BMW", "8 Series (G15)", 2019);
const driver1 = new Driver('Jane Roe', 35, fancyCar);
console.log(driver1.car.make); // logs: "BMW"
The Object()
constructor
The "built-in" Object(value)
constructor function,
that can be used with or without keyword new
,
turns the value into an object.
-
If the value is absent,
null
orundefined
, it will create and return an empty object. - If the value is a primitive, it will return a wrapper object corresponding to the given value.
- If the value is an object, it will simply return the object value.
Next examples all assign an empty object to a constant:
const myObject = new Object();
const myObject = Object();
const myObject = new Object(null);
const myObject = Object(undefined);
const myObject = {};
Next example creates a number wrapper object (see Instances of wrapper objects):
const myNumber = new Object(2);
console.log(myNumber); // logs: Number { 2 }
console.log(myNumber.valueOf()); // 2
The Object.create
method
Instead of a constructor function you can also use an object, a prototype object, to create derivative objects from.
This can be done by using the Object.create()
method.
const user = {
name: "full name",
avatar: "nickname",
nComments: 0,
displayAvatar() {
console.log(this.avatar);
}
};
const user1 = Object.create(user);
user1.avatar = 'Marge Bouvier';
user1.displayAvatar(); // logs: "Marge Bouvier"
console.log(user1); // logs: { avatar: "Marge Bouvier" } // only the own properties are shown
console.log(Object.getPrototypeOf(user1) ); // logs: { name: "full name", avatar: "nickname", nComments: 0, displayAvatar: displayAvatar() }
PS: The last two lines will be explained in the next chapter.
In this case the properties of the prototype object do not become own properties of the created object. The created object inherits the properties of the prototype object. All created objects with the same prototype object share the same inherited properties. Adding (inherited) properties, at run-time, to all created objects of the same type can be done via the prototype object. In the next chapter this will be explained in more detail.
const user = {
name: "full name",
avatar: "nickname",
nComments: 0,
displayAvatar() {
console.log(this.avatar);
}
};
const user1 = Object.create(user);
const user2 = Object.create(user);
user.avatar = 'Peaky Blinder';
user1.displayAvatar(); // logs: "Peaky Blinder"
user2.displayAvatar(); // logs: "Peaky Blinder"
user1.avatar = 'Basil Fawlty';
user1.displayAvatar(); // logs: "Basil Fawlty"
user2.displayAvatar(); // logs: "Peaky Blinder"
user.gender = "gender";
console.log(user1.gender); // logs: "gender"
console.log(user2.gender); // logs: "gender"
user1.gender = 'X';
console.log(user1.gender); // logs: "X"
console.log(user2.gender); // logs: "gender"