Objects in JavaScript - the basics

Object creation by Literal

Object creation by Literal

Object Literal (object initializer)

An object literal, also known as object initializer, is a comma-delimited list of zero or more pairs of property names and associated values of an object, enclosed in curly braces {}.

			const obj = {
				property1: value1,
				...
				propertyN: valueN
			};
		
The value of a property can by any JS data type: a primitive, array, function or any other object. When the value is a function we call that property method!

By object literals in JavaScript, we can create associative arrays/dictionaries data structures.

Object Literal - example


			const apple = {
				// define properties:
				color: "red",
				price: [3.5, 2, 2.5],

				// define methods:
				calcMinPrice: function(){
					return  Math.min( ...this.price ); // from ES6
				},
				calcMaxPrice: function(){
					return  Math.max( ...this.price ); // from ES6
				}
			}
			// objects usage:
			console.log(`apple min price: ${apple.calcMinPrice()}`);
		

Create empty object literal and add properties

We can create an object, by creating empty object literal and add the properties later

			// create empty object lieral:
			const obj = {};

			// add properties
			obj.property1 = value1;
			...
			obj.propertyN = valueN;
		

Object Literal: Pros&Cons

Pros
Simple and clear syntax for one instance
Cons
To much "copy-paste" syntax for multitude instances

Object properties

Object properties

Property names

Property names must be strings
If they are not, JavaScript try to typecast them

Accessing properties - the dot notation


			get = object.property;
			object.property = set;
		
property must be a valid identifier!

			var obj = {};

			obj.$1 = "first"; // valid
			obj.1  = "first"; // invalid
		

Accessing properties - square brackets notation


			get = object[property_name];
			object[property_name] = set;
		
property_name is a string, or expression that evaluates to string!
property_name can be any string, not necessarily valid identifier.

			var obj = {};
			var keyName = 2;

			obj["1"] = "first"; 	// valid
			obj[keyName]   = "second"; 	// valid

			console.log(obj)
			// Object {1: "first", 2: "second"}
		

Duplicate property names

An object can not have 2/more properties with a same name!
When 2/more properties with a same name are given, then the last of them will overwrite the others.

			var obj={
				prop1: 1,
				prop2: 2,
				prop1: 3,
				prop4: 4
			}
			console.log(obj);
			// Object {prop1: 3, prop2: 2, prop4: 4}
		

Computed property names (ES2015)

ES2015 spec allow an expression to be placed inside square brackets, which will be computed as the property name

			var i = 0;
			var obj = {
				[`key${++i}`] : i,
				[`key${++i}`] : i,
				[`key${++i}`] : i,
			};
			console.dir(obj);
			// Object
			// 	key1: 1
			// 	key2: 2
			// 	key3: 3

		

Shorthand property names (ES2015)


			var key1 = 'first', key2 = 'second';

			var obj = {key1, key2};

			console.log(obj);
			// Object {key1: "first", key2: "second"}

		

Shorthand method notation (ES2015)

We can omit the function keyword, when defining methods after ES2015

			var obj = {
				id: 1,
				sayID(){console.log(this.id)},
			}
			obj.sayID();
			// 1
		

Multiple Objects Creation

Multiple Objects Creation

Factory Function

We can define a function, which creates an object by given property values and return that object.
Pros: could be very flexible.
Cons: write everything by hand. Difficult to implement object inheritance.

Factory Function - example


			const appleFactory = function( color, prices ){
				const obj = {};

				// define properties:
				obj.color = color;
				obj.prices = prices;

				// define methods:
				obj.calcMinPrice = function(){
					return  Math.min( ...this.prices ); // from ES6
				};
				obj.calcMaxPrice = function(){
					return  Math.max( ...this.prices ); // from ES6
				};

				return obj;
			}

			// create object instances:
			const apple1 = appleFactory("red", [3.5, 2, 2.5]);
			const apple2 = appleFactory("green", [1.80, 2.10, 2.40]);

			// objects usage:
			console.log( "apple1 min price: ", apple1.calcMinPrice());
			console.log( "apple2 min price: ", apple2.calcMinPrice());
		

"Constructor" Function

Constructor function is a function which constructs objects.
Every function in JS can act as a Constructor function.
What make difference is the way you call the constructor function!
You must prefix the constructor function call with the keyword new, and only that will do the magic.

The new keyowrd

The new keyword does the following things:

Creates a blank, plain JavaScript object.
Links (sets the constructor of) this object to another object (will be discussed in further topics).
Passes the newly created object from Step 1 as the this context.
Returns this if the function doesn't return its own object.

"Constructor" Function - example


			const AppleConstructor = function( color, prices ){
				// define properties:
				this.color = color;
				this.prices = prices;

				// define methods:
				this.calcMinPrice = function(){
					return  Math.min( ...this.prices ); // from ES6
				};
				this.calcMaxPrice = function(){
					return  Math.max( ...this.prices ); // from ES6
				};
			}

			// create object instances:
			const apple3 = new AppleConstructor("red", [3.5, 2, 2.5]);
			const apple4 = new AppleConstructor("green", [1.80, 2.10, 2.40]);

			// objects usage:
			console.log( "apple3 min price: ", apple3.calcMinPrice());
			console.log( "apple4 min price: ", apple4.calcMinPrice());
		

"Constructor" Function: Pros&Cons

Pros
Easy to write (just set properties and methods). And when callled with new it will auto-magically care of object creation, including the inheritance.
Cons
new and this problems!

The class syntax

ES6 introduces the class syntax which makes it easier to write class-based OOP with JS.
The class syntax is just a syntactical sugar over JavaScript's existing prototype-based inheritance (will be discussed in further topics).
The class syntax does not introduce a new object-oriented inheritance model to JavaScript.

The class syntax - example


			class AppleClass{
				constructor( color, prices ){
					// define properties:
					this.color = color;
					this.prices = prices;
				}

				// define methods:
				calcMinPrice(){
					return  Math.min( ...this.prices ); // from ES6
				}

				calcMaxPrice(){
					return  Math.max( ...this.prices ); // from ES6
				}
			}


			// create object instances:
			const apple5 = new AppleClass("red", [3.5, 2, 2.5]);
			const apple6 = new AppleClass("green", [1.80, 2.10, 2.40]);

			// objects usage:
			console.log( "apple5 min price: ", apple5.calcMinPrice());
			console.log( "apple6 min price: ", apple6.calcMinPrice());
		

References:

Class syntax @MDN

Exercises

maxRectangleArea


			Represent the data, about 5 rectangles with next properties:

						id: r1, width: 40, height: 20
						id: r2, width: 30, height: 30
						id: r3, width: 10, height: 80
						id: r4, width: 90, height: 2
						id: r5, width: 20, height: 20

			Write a function which will return the id of the rectangle with biggest area.

			Expected output: r2
		

Solutions

Solutions

maxRectangleArea-ClassSolution


			/*TASK:
				Represent the data, about 5 rectangles with next properties:

					id: r1, width: 40, height: 20
					id: r2, width: 30, height: 30
					id: r3, width: 10, height: 80
					id: r4, width: 90, height: 2
					id: r5, width: 20, height: 20

				Write a function which will return the id of the rectangle with biggest area.

				Expected output: r2
			*/

			class Rectangle{
				static count = 0;

				constructor(width,height){
					// make rectangle id
					Rectangle.count+=1;
					this.id = `r${Rectangle.count}`
					this.width = width || console.log(`Please, give me a Rectangle width`);
					this.height = height || console.log(`Please, give me a Rectangle height`);
				}
				// getter:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get
				get area(){
					return this.width * this.height;
				}

			}
			function findRectangleWithMaxArea(rectangles){
				let currentMaxArea = 0;
				let currentMaxRectangleID = "";

				for (let i = 0; i < rectangles.length; i++) {
					const r = rectangles[i];

					if( r.area > currentMaxArea ){
						currentMaxArea = r.area;
						currentMaxRectangleID = r.id
					}
				}

				return currentMaxRectangleID;
			}

			let rectangles = [
				new Rectangle(40,20),
				new Rectangle(30,30),
				new Rectangle(10,80),
				new Rectangle(90,2),
				new Rectangle(20,20),
			];

			let maxRectangleId = findRectangleWithMaxArea(rectangles);
			console.log(`maxRectangleId: ${maxRectangleId}`);
		

maxRectangleArea-ConstructorSolution


			/*TASK:
				Represent the data, about 5 rectangles with next properties:

					id: r1, width: 40, height: 20
					id: r2, width: 30, height: 30
					id: r3, width: 10, height: 80
					id: r4, width: 90, height: 2
					id: r5, width: 20, height: 20

				Write a function which will return the id of the rectangle with biggest area.

				Expected output: r2
			*/

			function Rectangle(width,height) {
				// make rectangle id
				Rectangle.count+=1;
				this.id = `r${Rectangle.count}`
				this.width = width || console.log(`Please, give me a Rectangle width`);
				this.height = height || console.log(`Please, give me a Rectangle height`);
			}
			Rectangle.count = 0;
			Rectangle.prototype.calcArea = function (){
				return this.width * this.height;
			}
			// if you want to use getter instead => read:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get#defining_a_getter_on_new_objects_in_object_initializers


			function findRectangleWithMaxArea(rectangles){
				let currentMaxArea = 0;
				let currentMaxRectangleID = "";

				for (let i = 0; i < rectangles.length; i++) {
					const r = rectangles[i];
					const rArea = r.calcArea();

					if( rArea > currentMaxArea ){
						currentMaxArea = rArea;
						currentMaxRectangleID = r.id
					}
				}

				return currentMaxRectangleID;
			}

			let rectangles = [
				new Rectangle(40,20),
				new Rectangle(30,30),
				new Rectangle(10,80),
				new Rectangle(90,2),
				new Rectangle(20,20),
			];

			let maxRectangleId = findRectangleWithMaxArea(rectangles);
			console.log(`maxRectangleId: ${maxRectangleId}`);
		

maxRectangleArea-FactorySolution


			/*TASK:
				Represent the data, about 5 rectangles with next properties:

					id: r1, width: 40, height: 20
					id: r2, width: 30, height: 30
					id: r3, width: 10, height: 80
					id: r4, width: 90, height: 2
					id: r5, width: 20, height: 20

				Write a function which will return the id of the rectangle with biggest area.

				Expected output: r2
			*/


			function createRectangle(width,height) {
				createRectangle.count+=1;
				return {
					id:`r${createRectangle.count}`,
					width: width || console.log(`Please, give me a Rectangle width`),
					height: height || console.log(`Please, give me a Rectangle height`),
					// getter: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get#defining_a_getter_on_new_objects_in_object_initializers
					get area(){
						return this.width * this.height;
					}
				};
			}
			createRectangle.count = 0;


			function findRectangleWithMaxArea(rectangles){
				let currentMaxArea = 0;
				let currentMaxRectangleID = "";

				for (let i = 0; i < rectangles.length; i++) {
					const r = rectangles[i];
					const rArea = r.area;

					if( rArea > currentMaxArea ){
						currentMaxArea = rArea;
						currentMaxRectangleID = r.id
					}
				}

				return currentMaxRectangleID;
			}

			let rectangles = [
				createRectangle(40,20),
				createRectangle(30,30),
				createRectangle(10,80),
				createRectangle(90,2),
				createRectangle(20,20),
			];

			let maxRectangleId = findRectangleWithMaxArea(rectangles);
			console.log(`maxRectangleId: ${maxRectangleId}`);




		

These slides are based on

customised version of

Hakimel's reveal.js

framework