JavaScript Course 4: Objects: Difference between revisions
m Стадий: 6 [Фаза:Утвърждаване, Статус:Утвърден]; Категория:JavaScript |
m Text replacement - "mlw-continue" to "code-continue" |
||
Line 30: | Line 30: | ||
In JavaScript Objects are dynamic, so we can add additional properties and methods to them, despite of they are defined by keywords <code>var</code>, <code>let</code> or <code>const</code>. When we define an Object by <code>const</code> that means the type of the variable that holds the ''object'' is <code>const</code> and we can't change that type, but we can modify the created Object itself - changing the properties and methods of the Object . | In JavaScript Objects are dynamic, so we can add additional properties and methods to them, despite of they are defined by keywords <code>var</code>, <code>let</code> or <code>const</code>. When we define an Object by <code>const</code> that means the type of the variable that holds the ''object'' is <code>const</code> and we can't change that type, but we can modify the created Object itself - changing the properties and methods of the Object . | ||
In order to delete a '''member''' ('''property''' or '''method''') of an Object we can use the delete operator in the following way. <syntaxhighlight lang="javascript" class=" | In order to delete a '''member''' ('''property''' or '''method''') of an Object we can use the delete operator in the following way. <syntaxhighlight lang="javascript" class="code-continue"> | ||
delete circle.name; | delete circle.name; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Line 44: | Line 44: | ||
== Literal syntax of Object definition == | == Literal syntax of Object definition == | ||
<syntaxhighlight lang="javascript" class=" | <syntaxhighlight lang="javascript" class="code-continue"> | ||
const circle = { | const circle = { | ||
"name": "Circle 1", // Property of type String | "name": "Circle 1", // Property of type String | ||
Line 57: | Line 57: | ||
} | } | ||
}; | }; | ||
</syntaxhighlight><syntaxhighlight lang="javascript" class=" | </syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue"> | ||
console.log(circle); | console.log(circle); | ||
</syntaxhighlight><syntaxhighlight lang="shell-session"> | </syntaxhighlight><syntaxhighlight lang="shell-session"> | ||
Line 66: | Line 66: | ||
=== Dot notation === | === Dot notation === | ||
Call and assign a Property with Dot notation.<syntaxhighlight lang="javascript" class=" | Call and assign a Property with Dot notation.<syntaxhighlight lang="javascript" class="code-continue"> | ||
console.log(circle.name); | console.log(circle.name); | ||
</syntaxhighlight><syntaxhighlight lang="shell-session"> | </syntaxhighlight><syntaxhighlight lang="shell-session"> | ||
Circle 1 | Circle 1 | ||
</syntaxhighlight><syntaxhighlight lang="javascript" class=" | </syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue"> | ||
circle.isVisible = false; | circle.isVisible = false; | ||
console.log(circle.isVisible); | console.log(circle.isVisible); | ||
Line 78: | Line 78: | ||
=== Bracket notation === | === Bracket notation === | ||
Call and assign a Property with Bracket notation.<syntaxhighlight lang="javascript" class=" | Call and assign a Property with Bracket notation.<syntaxhighlight lang="javascript" class="code-continue"> | ||
console.log(circle['location']); | console.log(circle['location']); | ||
</syntaxhighlight><syntaxhighlight lang="shell-session"> | </syntaxhighlight><syntaxhighlight lang="shell-session"> | ||
{x: 1, y: 1} | {x: 1, y: 1} | ||
</syntaxhighlight><syntaxhighlight lang="javascript" class=" | </syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue"> | ||
circle.location['x'] = 2; | circle.location['x'] = 2; | ||
circle.location.y = 3; | circle.location.y = 3; | ||
Line 91: | Line 91: | ||
=== Methods and Dot notation === | === Methods and Dot notation === | ||
When a Function is a part of an Object in the terms of OOP we calling this Function a Method. Methods could be called and defined only with Dot notation.<syntaxhighlight lang="javascript" class=" | When a Function is a part of an Object in the terms of OOP we calling this Function a Method. Methods could be called and defined only with Dot notation.<syntaxhighlight lang="javascript" class="code-continue"> | ||
circle.draw(); | circle.draw(); | ||
</syntaxhighlight><syntaxhighlight lang="shell-session"> | </syntaxhighlight><syntaxhighlight lang="shell-session"> | ||
Draw a circle with: 2 3 1 | Draw a circle with: 2 3 1 | ||
</syntaxhighlight><syntaxhighlight lang="javascript" class=" | </syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue"> | ||
circle.radius = 2; | circle.radius = 2; | ||
circle.area = function() { | circle.area = function() { | ||
Line 112: | Line 112: | ||
Step 1, move the object definition inside :the Factory function and return it as output of that function: | Step 1, move the object definition inside :the Factory function and return it as output of that function: | ||
| | | | ||
<syntaxhighlight lang="javascript" class=" | <syntaxhighlight lang="javascript" class="code-continue"> | ||
function createCircle() { | function createCircle() { | ||
const circle = { | const circle = { | ||
Line 133: | Line 133: | ||
Step 2, simplify the above and just return the object definition. | Step 2, simplify the above and just return the object definition. | ||
| | | | ||
<syntaxhighlight lang="javascript" class=" | <syntaxhighlight lang="javascript" class="code-continue"> | ||
function createCircle() { | function createCircle() { | ||
return { | return { | ||
Line 153: | Line 153: | ||
Step 3, convert hard codded values as parameters, which values will be supply as arguments when we calling the Factory function. | Step 3, convert hard codded values as parameters, which values will be supply as arguments when we calling the Factory function. | ||
| | | | ||
<syntaxhighlight lang="javascript" class=" | <syntaxhighlight lang="javascript" class="code-continue"> | ||
function createCircle(name, radius, location, isVisible) { | function createCircle(name, radius, location, isVisible) { | ||
return { | return { | ||
Line 167: | Line 167: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
|l=#Step 3}} | |l=#Step 3}} | ||
{{collapse|Step 4, in modern JS if the key and the value are the same we can make our code shorter, and removing the value and simply adding the key.|<syntaxhighlight lang="javascript" class=" | {{collapse|Step 4, in modern JS if the key and the value are the same we can make our code shorter, and removing the value and simply adding the key.|<syntaxhighlight lang="javascript" class="code-continue"> | ||
function createCircle(name, radius, location, isVisible) { | function createCircle(name, radius, location, isVisible) { | ||
return { | return { | ||
Line 185: | Line 185: | ||
Step 5, simplify the Methods definitions, like we define a function outside of an object, but we can dropping the ''function'' keyword. | Step 5, simplify the Methods definitions, like we define a function outside of an object, but we can dropping the ''function'' keyword. | ||
| | | | ||
<syntaxhighlight lang="javascript" class=" | <syntaxhighlight lang="javascript" class="code-continue"> | ||
function createCircle(name, radius, location, isVisible) { | function createCircle(name, radius, location, isVisible) { | ||
return { | return { | ||
Line 198: | Line 198: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
|l=#The final result, Step 5|c=false}}'''Use the Factory function.'''<syntaxhighlight lang="javascript" class=" | |l=#The final result, Step 5|c=false}}'''Use the Factory function.'''<syntaxhighlight lang="javascript" class="code-continue"> | ||
const circle1 = createCircle("Circle 1", 2, {x: 1, y: 2}, true); | const circle1 = createCircle("Circle 1", 2, {x: 1, y: 2}, true); | ||
</syntaxhighlight><syntaxhighlight lang="javascript" class=" | </syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue"> | ||
console.log(circle1); | console.log(circle1); | ||
</syntaxhighlight><syntaxhighlight lang="shell-session"> | </syntaxhighlight><syntaxhighlight lang="shell-session"> | ||
{name: 'Circle 1', radius: 2, location: {…}, visible: true, draw: ƒ} | {name: 'Circle 1', radius: 2, location: {…}, visible: true, draw: ƒ} | ||
</syntaxhighlight><syntaxhighlight lang="javascript" class=" | </syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue"> | ||
const circle2 = createCircle("Circle 2", 4, {x: 2, y: 2}, true); | const circle2 = createCircle("Circle 2", 4, {x: 2, y: 2}, true); | ||
</syntaxhighlight><syntaxhighlight lang="javascript" class=" | </syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue"> | ||
console.log(circle2); | console.log(circle2); | ||
</syntaxhighlight><syntaxhighlight lang="shell-session"> | </syntaxhighlight><syntaxhighlight lang="shell-session"> | ||
Line 214: | Line 214: | ||
The purpose of the Constructor functions is the same as the Factory functions - they produce Objects, it's just another approach. | The purpose of the Constructor functions is the same as the Factory functions - they produce Objects, it's just another approach. | ||
The naming convention for the Factory functions is: <code>PascalNotation</code><syntaxhighlight lang="javascript" class=" | The naming convention for the Factory functions is: <code>PascalNotation</code><syntaxhighlight lang="javascript" class="code-continue"> | ||
function Circle(name, radius, location, isVisible) { | function Circle(name, radius, location, isVisible) { | ||
this.name = name; | this.name = name; | ||
Line 228: | Line 228: | ||
const circle3 = new Circle("Circle 3", 6, {x: 2, y: 4}, true); | const circle3 = new Circle("Circle 3", 6, {x: 2, y: 4}, true); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="javascript" class=" | <syntaxhighlight lang="javascript" class="code-continue"> | ||
console.log(circle3); | console.log(circle3); | ||
</syntaxhighlight><syntaxhighlight lang="shell-session"> | </syntaxhighlight><syntaxhighlight lang="shell-session"> | ||
Circle {name: 'Circle 3', radius: 6, location: {…}, isVisible: true, draw: ƒ} | Circle {name: 'Circle 3', radius: 6, location: {…}, isVisible: true, draw: ƒ} | ||
</syntaxhighlight><syntaxhighlight lang="javascript" class=" | </syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue"> | ||
circle3.draw(); | circle3.draw(); | ||
</syntaxhighlight><syntaxhighlight lang="shell-session"> | </syntaxhighlight><syntaxhighlight lang="shell-session"> | ||
Line 251: | Line 251: | ||
An important difference between '''function declarations''' and '''class declarations''' is that while functions can be called in code that appears before they are defined, classes must be defined before they can be constructed. Code like the following will throw a <code>ReferenceError</code>: | An important difference between '''function declarations''' and '''class declarations''' is that while functions can be called in code that appears before they are defined, classes must be defined before they can be constructed. Code like the following will throw a <code>ReferenceError</code>: | ||
The naming convention for the Classes (as the Factory functions) is: <code>PascalNotation</code><syntaxhighlight lang="javascript" class=" | The naming convention for the Classes (as the Factory functions) is: <code>PascalNotation</code><syntaxhighlight lang="javascript" class="code-continue"> | ||
class Circle { | class Circle { | ||
constructor(name, radius, location, isVisible) { | constructor(name, radius, location, isVisible) { | ||
Line 267: | Line 267: | ||
const circle4 = new Circle("Circle 4", 8, {x: 6, y: 6}, false); | const circle4 = new Circle("Circle 4", 8, {x: 6, y: 6}, false); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="javascript" class=" | <syntaxhighlight lang="javascript" class="code-continue"> | ||
console.log(circle4); | console.log(circle4); | ||
</syntaxhighlight><syntaxhighlight lang="shell-session"> | </syntaxhighlight><syntaxhighlight lang="shell-session"> | ||
Line 273: | Line 273: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Constructor Property == | == Constructor Property == | ||
Every Object has a constructor property that show the function that we use to create the object.<syntaxhighlight lang="javascript" class=" | Every Object has a constructor property that show the function that we use to create the object.<syntaxhighlight lang="javascript" class="code-continue"> | ||
let x = {}; | let x = {}; | ||
console.log(x.constructor); | console.log(x.constructor); | ||
</syntaxhighlight><syntaxhighlight lang="shell-session"> | </syntaxhighlight><syntaxhighlight lang="shell-session"> | ||
ƒ Object() {[native code]} | ƒ Object() {[native code]} | ||
</syntaxhighlight><syntaxhighlight lang="javascript" class=" | </syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue"> | ||
let x = new String('ABC'); | let x = new String('ABC'); | ||
console.log(x.constructor); | console.log(x.constructor); | ||
</syntaxhighlight><syntaxhighlight lang="shell-session"> | </syntaxhighlight><syntaxhighlight lang="shell-session"> | ||
ƒ String() {[native code]} | ƒ String() {[native code]} | ||
</syntaxhighlight><syntaxhighlight lang="javascript" class=" | </syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue"> | ||
let x = 'ABC'; | let x = 'ABC'; | ||
console.log(x.constructor); | console.log(x.constructor); | ||
Line 299: | Line 299: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="javascript" class=" | <syntaxhighlight lang="javascript" class="code-continue"> | ||
console.log(Circle.name); | console.log(Circle.name); | ||
</syntaxhighlight><syntaxhighlight lang="shell-session"> | </syntaxhighlight><syntaxhighlight lang="shell-session"> | ||
'Circle' | 'Circle' | ||
</syntaxhighlight><syntaxhighlight lang="javascript" class=" | </syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue"> | ||
console.log(Circle.length); // will return the number of arguments | console.log(Circle.length); // will return the number of arguments | ||
</syntaxhighlight><syntaxhighlight lang="shell-session"> | </syntaxhighlight><syntaxhighlight lang="shell-session"> | ||
1 | 1 | ||
</syntaxhighlight><syntaxhighlight lang="javascript" class=" | </syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue"> | ||
console.log(Circle.constructor); // will return the constructor function | console.log(Circle.constructor); // will return the constructor function | ||
</syntaxhighlight><syntaxhighlight lang="shell-session"> | </syntaxhighlight><syntaxhighlight lang="shell-session"> | ||
Line 322: | Line 322: | ||
'''1.A.''' Example with primitives - when we copy the value of a Primitive type we create an independent variable: | '''1.A.''' Example with primitives - when we copy the value of a Primitive type we create an independent variable: | ||
<syntaxhighlight lang="javascript" class=" | <syntaxhighlight lang="javascript" class="code-continue"> | ||
let x = 10; | let x = 10; | ||
let y = x; | let y = x; | ||
Line 333: | Line 333: | ||
'''1.B.''' Example with references - when we copy the value or Reference type we copy the reference, not the value: | '''1.B.''' Example with references - when we copy the value or Reference type we copy the reference, not the value: | ||
<syntaxhighlight lang="javascript" class=" | <syntaxhighlight lang="javascript" class="code-continue"> | ||
let x = {value: 10}; | let x = {value: 10}; | ||
let y = x; | let y = x; | ||
x.value = 20; | x.value = 20; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="javascript" class=" | <syntaxhighlight lang="javascript" class="code-continue"> | ||
console.log(x); | console.log(x); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="shell-session" class=" | <syntaxhighlight lang="shell-session" class="code-continue"> | ||
{value: 20} | {value: 20} | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="javascript" class=" | <syntaxhighlight lang="javascript" class="code-continue"> | ||
console.log(y); | console.log(y); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Line 352: | Line 352: | ||
'''2.A.''' Another example with Primitive types: | '''2.A.''' Another example with Primitive types: | ||
<syntaxhighlight lang="javascript" class=" | <syntaxhighlight lang="javascript" class="code-continue"> | ||
let number = 10; | let number = 10; | ||
Line 361: | Line 361: | ||
increase(number); | increase(number); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="javascript" class=" | <syntaxhighlight lang="javascript" class="code-continue"> | ||
console.log(number); | console.log(number); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="shell-session" class=" | <syntaxhighlight lang="shell-session" class="code-continue"> | ||
10 | 10 | ||
</syntaxhighlight>When we pass the variable <code>number</code> as an argument of the function <code>increase(number)</code>, there is created a ''local variable'' (inside the function) that is completely different of the ''global variable'' <code>number</code>, so the value of the global variable is not changed. | </syntaxhighlight>When we pass the variable <code>number</code> as an argument of the function <code>increase(number)</code>, there is created a ''local variable'' (inside the function) that is completely different of the ''global variable'' <code>number</code>, so the value of the global variable is not changed. | ||
'''2.B.''' Another example with Reference types: | '''2.B.''' Another example with Reference types: | ||
<syntaxhighlight lang="javascript" class=" | <syntaxhighlight lang="javascript" class="code-continue"> | ||
let object = {value: 10}; | let object = {value: 10}; | ||
Line 378: | Line 378: | ||
increase(object); | increase(object); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="javascript" class=" | <syntaxhighlight lang="javascript" class="code-continue"> | ||
console.log(object); | console.log(object); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="shell-session" class=" | <syntaxhighlight lang="shell-session" class="code-continue"> | ||
{value: 11} | {value: 11} | ||
</syntaxhighlight>In this example wen we pass the <code>object</code> as argument to the function it is passed as its reference. So we have two variables <code>object</code> and <code>obj</code> that pointing to the same (internal JS) object. | </syntaxhighlight>In this example wen we pass the <code>object</code> as argument to the function it is passed as its reference. So we have two variables <code>object</code> and <code>obj</code> that pointing to the same (internal JS) object. | ||
Line 391: | Line 391: | ||
draw() {console.log("Draw...");} | draw() {console.log("Draw...");} | ||
}; | }; | ||
</syntaxhighlight><syntaxhighlight lang="javascript" class=" | </syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue"> | ||
for (let key in circle) | for (let key in circle) | ||
console.log(`${key} : ${circle[key]}`); | console.log(`${key} : ${circle[key]}`); | ||
Line 398: | Line 398: | ||
radius : 1 | radius : 1 | ||
draw : draw() {console.log("Draw...");} | draw : draw() {console.log("Draw...");} | ||
</syntaxhighlight><syntaxhighlight lang="javascript" class=" | </syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue"> | ||
// Object.keys(circle) returns an Array of keys of the circle 'object', which array is iterative | // Object.keys(circle) returns an Array of keys of the circle 'object', which array is iterative | ||
for (let key of Object.keys(circle)) | for (let key of Object.keys(circle)) | ||
Line 407: | Line 407: | ||
radius : 1 | radius : 1 | ||
draw : draw() {console.log("Draw...");} | draw : draw() {console.log("Draw...");} | ||
</syntaxhighlight><syntaxhighlight lang="javascript" class=" | </syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue"> | ||
// Object.keys(circle) returns an Array of keys of the circle 'object', which array is iterative | // Object.keys(circle) returns an Array of keys of the circle 'object', which array is iterative | ||
for (let entry of Object.entries(circle)) | for (let entry of Object.entries(circle)) | ||
Line 416: | Line 416: | ||
(2) ['radius', 1] | (2) ['radius', 1] | ||
(2) ['draw', ƒ] | (2) ['draw', ƒ] | ||
</syntaxhighlight>If given property or method exists example:<syntaxhighlight lang="javascript" class=" | </syntaxhighlight>If given property or method exists example:<syntaxhighlight lang="javascript" class="code-continue"> | ||
if ('radius' in circle) console.log('YES'); | if ('radius' in circle) console.log('YES'); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Line 429: | Line 429: | ||
draw() {console.log("Draw...");} | draw() {console.log("Draw...");} | ||
}; | }; | ||
</syntaxhighlight>The old approach - iterate over the keys of an exiting object and copy their values to the new object.<syntaxhighlight lang="javascript" class=" | </syntaxhighlight>The old approach - iterate over the keys of an exiting object and copy their values to the new object.<syntaxhighlight lang="javascript" class="code-continue"> | ||
const another = {}; | const another = {}; | ||
for (let key in circle) | for (let key in circle) | ||
another[key] = circle[key]; | another[key] = circle[key]; | ||
</syntaxhighlight><syntaxhighlight lang="javascript" class=" | </syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue"> | ||
console.log(another); | console.log(another); | ||
Line 439: | Line 439: | ||
<syntaxhighlight lang="shell-session"> | <syntaxhighlight lang="shell-session"> | ||
{radius: 1, draw: ƒ} | {radius: 1, draw: ƒ} | ||
</syntaxhighlight>The modern approach - use <code>Object.assign()</code> which copies all properties and methods from one or more objects to a new object.<syntaxhighlight lang="javascript" class=" | </syntaxhighlight>The modern approach - use <code>Object.assign()</code> which copies all properties and methods from one or more objects to a new object.<syntaxhighlight lang="javascript" class="code-continue"> | ||
const another = Object.assign({}, circle); | const another = Object.assign({}, circle); | ||
</syntaxhighlight><syntaxhighlight lang="javascript" class=" | </syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue"> | ||
console.log(another); | console.log(another); | ||
Line 447: | Line 447: | ||
<syntaxhighlight lang="shell-session"> | <syntaxhighlight lang="shell-session"> | ||
{radius: 1, draw: ƒ} | {radius: 1, draw: ƒ} | ||
</syntaxhighlight>Clone an Object and add an additional property or method to the new object.<syntaxhighlight lang="javascript" class=" | </syntaxhighlight>Clone an Object and add an additional property or method to the new object.<syntaxhighlight lang="javascript" class="code-continue"> | ||
const another = Object.assign({"color": "yellow"}, circle); | const another = Object.assign({"color": "yellow"}, circle); | ||
</syntaxhighlight><syntaxhighlight lang="javascript" class=" | </syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue"> | ||
console.log(another); | console.log(another); | ||
Line 458: | Line 458: | ||
A simile and elegant way to clone an object - by using the Spread operator: <code class="noTypo">...</code> | A simile and elegant way to clone an object - by using the Spread operator: <code class="noTypo">...</code> | ||
<syntaxhighlight lang="javascript" class=" | <syntaxhighlight lang="javascript" class="code-continue"> | ||
const another = {...circle}; | const another = {...circle}; | ||
</syntaxhighlight><syntaxhighlight lang="javascript" class=" | </syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue"> | ||
console.log(another); | console.log(another); | ||
Latest revision as of 07:29, 26 September 2022
References
- Code with Mosh: The Ultimate JavaScript Mastery Series – Part 1
- Geeks for Geeks: Creating objects in JavaScript (4 Different Ways)
- MDM Web Docs: JavaScript > JavaScript reference > Classes
- W3School: JavaScript Objects
- W3School: JavaScript Classes
- W3School: JavaScript Object Accessors – Getters and Setters
See also:
Basics
Object oriented programming (OOP) is a style of programming where we see a program as a collection of Objects, that talk to each other to perform some functionality. The Objects has:
- Properties – primitives defined by
"keys":
and"values",
- Methods – internal
functions()
that operates with the properties of the object.
We can access the Properties of an Object via:
- Dot notation:
object.proprtyName;
- Bracket notation:
object['proprtyName'];
Using Dot notation is cleaner and easier, but the Bracket notation could be used when we want to pass variable in the place of the key – i.e. when when using a loop or so.
We can access the Methods of an Object via:
- Dot notation (only):
object.methodName();
object.methodName = function() {…};
In JavaScript Objects are dynamic, so we can add additional properties and methods to them, despite of they are defined by keywords var
, let
or const
. When we define an Object by const
that means the type of the variable that holds the object is const
and we can't change that type, but we can modify the created Object itself – changing the properties and methods of the Object .
In order to delete a member (property or method) of an Object we can use the delete operator in the following way.
delete circle.name;
Ways to create an Object in JavaScript
With JavaScript, you can define and create your own objects. There are different ways to create new objects:
- Create a single object, using an Object literal.
- Create a single object, with the keyword
new
. - Define Object Factory function, and then generate a new object by this function.
- Define an Object Constructor function, and then create objects of the constructed type.
- Create an object using
Object.create()
. - ES6 Classes.
Literal syntax of Object definition
const circle = {
"name": "Circle 1", // Property of type String
"radius": 1, // Property of type Number
"location": { // Property of type Object
"x": 1,
"y": 1
},
"isVisible": true, // Property of type Boolean
"draw": function() { // Method: a property of type Function
console.log("Draw a circle with:", this.location.x, this.location.y, this.radius);
}
};
console.log(circle);
{name: 'Circle 1', radius: 1, location: {…}, isVisible: true, draw: ƒ}
Access Properties and Methods
Dot notation
Call and assign a Property with Dot notation.
console.log(circle.name);
Circle 1
circle.isVisible = false;
console.log(circle.isVisible);
false
Bracket notation
Call and assign a Property with Bracket notation.
console.log(circle['location']);
{x: 1, y: 1}
circle.location['x'] = 2;
circle.location.y = 3;
console.log(circle.location.x, circle.location['y']);
2 3
Methods and Dot notation
When a Function is a part of an Object in the terms of OOP we calling this Function a Method. Methods could be called and defined only with Dot notation.
circle.draw();
Draw a circle with: 2 3 1
circle.radius = 2;
circle.area = function() {
return this.radius * this.radius * 3.14;
};
console.log(circle.area());
12.56
Factory Functions for Objects definition
Just like a factory produce products, the Factory functions produce Objects. Here is how to transform the Object literal definition into a factory function.
The naming convention for the Factory functions is: kamelNotation
Step 1, move the object definition inside :the Factory function and return it as output of that function:
function createCircle() {
const circle = {
"name": "Circle 1", // Property of type String
"radius": 1, // Property of type Number
"location": { // Property of type Object
"x": 1,
"y": 1
},
"isVisible": true, // Property of type Boolean
"draw": function() { // Method: a property of type Function
console.log("Draw a circle with:", this.location.x, this.location.y, this.radius);
}
};
return circle;
}
Step 2, simplify the above and just return the object definition.
function createCircle() {
return {
"name": "Circle 1", // Property of type String
"radius": 1, // Property of type Number
"location": { // Property of type Object
"x": 1,
"y": 1
},
"isVisible": true, // Property of type Boolean
"draw": function() { // Method: a property of type Function
console.log("Draw a circle with:", this.location.x, this.location.y, this.radius);
}
};
}
Step 3, convert hard codded values as parameters, which values will be supply as arguments when we calling the Factory function.
function createCircle(name, radius, location, isVisible) {
return {
"name": name,
"radius": radius,
"location": location,
"isVisible": visible,
"draw": function() {
console.log("Draw a circle with:", this.location.x, this.location.y, this.radius);
}
};
}
Step 4, in modern JS if the key and the value are the same we can make our code shorter, and removing the value and simply adding the key.
function createCircle(name, radius, location, isVisible) {
return {
name,
radius,
location,
visible,
"draw": function() {
console.log("Draw a circle with:", this.location.x, this.location.y, this.radius);
}
};
}
Step 5, simplify the Methods definitions, like we define a function outside of an object, but we can dropping the function keyword.
function createCircle(name, radius, location, isVisible) {
return {
name,
radius,
location,
visible,
draw() {
console.log("Draw a circle with:", this.location.x, this.location.y, this.radius);
}
};
}
Use the Factory function.
const circle1 = createCircle("Circle 1", 2, {x: 1, y: 2}, true);
console.log(circle1);
{name: 'Circle 1', radius: 2, location: {…}, visible: true, draw: ƒ}
const circle2 = createCircle("Circle 2", 4, {x: 2, y: 2}, true);
console.log(circle2);
{name: 'Circle 2', radius: 4, location: {…}, visible: true, draw: ƒ}
Constructor Functions for Objects definition
The purpose of the Constructor functions is the same as the Factory functions – they produce Objects, it's just another approach.
The naming convention for the Factory functions is: PascalNotation
function Circle(name, radius, location, isVisible) {
this.name = name;
this.radius = radius;
this.location = location;
this.isVisible = isVisible;
this.draw = function() {
console.log("Draw a circle with:", this.location.x, this.location.y, this.radius);
};
}
Use the Constructor function.
const circle3 = new Circle("Circle 3", 6, {x: 2, y: 4}, true);
console.log(circle3);
Circle {name: 'Circle 3', radius: 6, location: {…}, isVisible: true, draw: ƒ}
circle3.draw();
Draw a circle with: 2 4 6
When we use the new
operator three things happen:
- The
new
operator creates an empty JavaScript Object, something like this:constant x = {};
- Then
new
setthis
of the Constructor function to point to the new empty Object. - Finally
new
returns the new Object from the constructor function, but we don't need explicitly add areturn
statement.
Classes for Objects definition
The purpose of the Classes is the same as the Factory and Constructor functions – they produce Objects. It's just another modern approach defined in ES6 (ES2015).
Classes are a template for creating objects. They encapsulate data with code to work on that data. Classes in JS are built on prototypes but also have some syntax and semantics that are not shared with ES5 class-like semantics.
Classes are in fact "special functions", and just as you can define function expressions and function declarations, the class syntax has two components: class expressions and class declarations.
An important difference between function declarations and class declarations is that while functions can be called in code that appears before they are defined, classes must be defined before they can be constructed. Code like the following will throw a ReferenceError
:
The naming convention for the Classes (as the Factory functions) is: PascalNotation
class Circle {
constructor(name, radius, location, isVisible) {
this.name = name;
this.radius = radius;
this.location = location;
this.isVisible = isVisible;
}
draw() {
console.log("Draw a circle with:", this.location.x, this.location.y, this.radius);
}
}
Use the Constructor function. The usage is the same as the Constructor functions by using the new
operator.
const circle4 = new Circle("Circle 4", 8, {x: 6, y: 6}, false);
console.log(circle4);
Circle {name: 'Circle 4', radius: 8, location: {…}, isVisible: false, draw: ƒ}
Constructor Property
Every Object has a constructor property that show the function that we use to create the object.
let x = {};
console.log(x.constructor);
ƒ Object() {[native code]}
let x = new String('ABC');
console.log(x.constructor);
ƒ String() {[native code]}
let x = 'ABC';
console.log(x.constructor);
ƒ String() {[native code]}
Functions and Arrays are Objects
In JavaScript the Functions (and Arrays) are also Objects. There is a built-in constructor function called Function that creates the objects of the functions. So the Functions also have methods and properties.
function Circle(radius) {
this.radius = radius;
this.draw = function() {
console.log("Draw circle radius:", this.radius);
}
}
console.log(Circle.name);
'Circle'
console.log(Circle.length); // will return the number of arguments
1
console.log(Circle.constructor); // will return the constructor function
ƒ Function() {[native code]}
See also Call and Apply methods:
- W3School: JavaScript Function Call(), that will call a function with specific context and will pass custom arguments to it.
- W3School: JavaScript Function Apply(), that will call a function with specific context and will pass an array of custom arguments to it.
Value vs Reference types
The Value types, also called Primitive types – Strings, Numbers, Booleans, undefined, null, Symbol – holds the value inside the variable of the primitive. In other hand the Reference types – Objects, Arrays, Functions – holds a reverence to an internal variable(s) where the actual value is stored.
Primitives are copied by their value. Objects (reference types) are copied by their reference.
1.A. Example with primitives – when we copy the value of a Primitive type we create an independent variable:
let x = 10;
let y = x;
x = 20;
console.log(x, y); // We can see 'x' and 'y' are two indepentant variables
20 10
1.B. Example with references – when we copy the value or Reference type we copy the reference, not the value:
let x = {value: 10};
let y = x;
x.value = 20;
console.log(x);
{value: 20}
console.log(y);
{value: 20}
2.A. Another example with Primitive types:
let number = 10;
function increase(num) {
num++;
}
increase(number);
console.log(number);
10
When we pass the variable number
as an argument of the function increase(number)
, there is created a local variable (inside the function) that is completely different of the global variable number
, so the value of the global variable is not changed.
2.B. Another example with Reference types:
let object = {value: 10};
function increase(obj) {
obj.value++;
}
increase(object);
console.log(object);
{value: 11}
In this example wen we pass the object
as argument to the function it is passed as its reference. So we have two variables object
and obj
that pointing to the same (internal JS) object.
Enumerating Properties of an Object
const circle = {
"radius": 1,
draw() {console.log("Draw...");}
};
for (let key in circle)
console.log(`${key} : ${circle[key]}`);
radius : 1
draw : draw() {console.log("Draw...");}
// Object.keys(circle) returns an Array of keys of the circle 'object', which array is iterative
for (let key of Object.keys(circle))
console.log(`${key} : ${circle[key]}`);
radius : 1
draw : draw() {console.log("Draw...");}
// Object.keys(circle) returns an Array of keys of the circle 'object', which array is iterative
for (let entry of Object.entries(circle))
console.log(entry);
(2) ['radius', 1]
(2) ['draw', ƒ]
If given property or method exists example:
if ('radius' in circle) console.log('YES');
YES
Clone an Object
const circle = {
"radius": 1,
draw() {console.log("Draw...");}
};
The old approach – iterate over the keys of an exiting object and copy their values to the new object.
const another = {};
for (let key in circle)
another[key] = circle[key];
console.log(another);
{radius: 1, draw: ƒ}
The modern approach – use Object.assign()
which copies all properties and methods from one or more objects to a new object.
const another = Object.assign({}, circle);
console.log(another);
{radius: 1, draw: ƒ}
Clone an Object and add an additional property or method to the new object.
const another = Object.assign({"color": "yellow"}, circle);
console.log(another);
{color: 'yellow', radius: 1, draw: ƒ}
A simile and elegant way to clone an object – by using the Spread operator: ...
const another = {...circle};
console.log(another);
{radius: 1, draw: ƒ}