Object Oriented Programming Flashcards
Cards, resources and exercises of OOP in Javascript.
Create a Basic JavaScript Object
Think about things people see everyday, like cars, shops, and birds. These are all objects: tangible things people can observe and interact with.
What are some qualities of these objects? A car has wheels. Shops sell items. Birds have wings.
These qualities, or properties, define what makes up an object. Note that similar objects share the same properties, but may have different values for those properties. For example, all cars have wheels, but not all cars have the same number of wheels.
Objects in JavaScript are used to model real-world objects, giving them properties and behavior just like their real-world counterparts. Here’s an example using these concepts to create a duck object:
let duck = { name: "Aflac", numLegs: 2 }; This duck object has two property/value pairs: a name of "Aflac" and a numLegs of 2.
Create a dog object with name and numLegs properties, and set them to a string and a number, respectively.
let dog = {
name : “Ninho”,
numLegs: 4
};
Use Dot Notation to Access the Properties of an Object
let dog = { name: "Spot", numLegs: 4 };
console. log(dog.name);
console. log(dog.numLegs);
Create a Method on an Object
Possible Solution
let dog = { name: "Spot", numLegs: 4, sayLegs: () => { return `This dog has ${dog.numLegs} legs.`; } };
console.log(dog.sayLegs());
Make Code More Reusable with the this Keyword
Access a property of an object with this keyword.
Possible Solution
let dog = { name: "Spot", numLegs: 4, sayLegs: function() { return `This dog has ${this.numLegs} legs.`; } };
console.log(dog.sayLegs());
Obs.: Arrow function doesn’t work here because this type of function has your own scope. So this keyword invoke to access property numLegs it causes undefined error.
How to Creates a constructor function ?
Constructors follow a few conventions:
Constructors are defined with a capitalized name to distinguish them from other functions that are not constructors.
Constructors use the keyword this to set properties of the object they will create. Inside the constructor, this refers to the new object it will create.
Constructors define properties and behaviors instead of returning a value as other functions might.
function Dog(){ this.name = "Bartô", this.color = "Yellow", this.numLegs = 4; }
Use a Constructor to Create Objects
Here’s the Bird constructor from the previous challenge:
function Bird() { this.name = "Albert"; this.color = "blue"; this.numLegs = 2; // "this" inside the constructor always refers to the object being created }
let blueBird = new Bird(); Notice that the new operator is used when calling a constructor. This tells JavaScript to create a new instance of Bird called blueBird. Without the new operator, this inside the constructor would not point to the newly created object, giving unexpected results.
Now blueBird has all the properties defined inside the Bird constructor:
blueBird.name; // => Albert
blueBird.color; // => blue
blueBird.numLegs; // => 2
Just like any other object, its properties can be accessed and modified:
blueBird.name = ‘Elvira’;
blueBird.name; // => Elvira
Use the Dog constructor from the last lesson to create a new instance of Dog, assigning it to a variable hound.
function Dog() { this.name = "Rupert"; this.color = "brown"; this.numLegs = 4; } // Add your code below this line
let hound = new Dog();
console. log(hound.name);
console. log(hound.color);
console. log(hound.numLegs);
Extend Constructors to Receive Arguments
Create a constructor which receive arguments. Then set this args to respective properties.
function Dog(name, color) { this.name = name; this.color = color; this.numLegs = 4; }
let terrier = new Dog(‘Barto’, ‘Brown’);
console. log(terrier.name);
console. log(terrier.color);
console. log(terrier.numLegs);
How to verify if an object is instance of a constructor ?
function House(numBedrooms) { this.numBedrooms = numBedrooms; }
// Add your code below this line let myHouse = new House(1);
myHouse instanceof House // returns true
Obs.: If an object is created without using a constructor, instanceof will verify that it is not an instance of that constructo and then returns false.
Check if the property is own property of a constructor object.
Understand Own Properties
In the following example, the Bird constructor defines two properties: name and numLegs:
function Bird(name) { this.name = name; this.numLegs = 2; }
let duck = new Bird("Donald"); let canary = new Bird("Tweety"); name and numLegs are called own properties, because they are defined directly on the instance object. That means that duck and canary each has its own separate copy of these properties.
In fact every instance of Bird will have its own copy of these properties.
The following code adds all of the own properties of duck to the array ownProps:
let ownProps = [];
for (let property in duck) { if(duck.hasOwnProperty(property)) { ownProps.push(property); } }
console.log(ownProps); // prints [ “name”, “numLegs” ]
Use Prototype Properties to Reduce Duplicate Code
Creates a object constructor with some properties. Then create a property witch sets value default to all instances of this constructor.
function Dog(name) { this.name = name; Dog.prototype.numLegs = 2; }
let beagle = new Dog("Snoopy"); let husky = new Dog("Zeus");
console. log(beagle.name);
console. log(beagle.numLegs);
console. log(husky.name);
console. log(husky.numLegs);
Iterate Over All Properties
You have now seen two kinds of properties: own properties and prototype properties. Own properties are defined directly on the object instance itself. And prototype properties are defined on the prototype.
Add all of the own properties of beagle to the array ownProps. Add all of the prototype properties of Dog to the array prototypeProps.
Possible Solution
function Dog(name) { this.name = name; }
Dog.prototype.numLegs = 4;
let beagle = new Dog(“Snoopy”);
let ownProps = []; let prototypeProps = [];
// Add your code below this line
for(let prop in beagle){ if(beagle.hasOwnProperty(prop)){ ownProps.push(prop); } else{ prototypeProps.push(prop); } }
console. log(ownProps);
console. log(prototypeProps);
How to access constructor property of a object to check this type ?
Possible Solution
function Dog(name) { this.name = name; }
function joinDogFraternity(candidate) { return candidate.constructor === Dog ? true : false; }
console.log(joinDogFraternity({}));
Note
Since the constructor property can be overwritten (which will be covered in the next two challenges) it’s generally better to use the instanceof method to check the type of an object.
Change the Prototype to a New Object
Up until now you have been adding properties to the prototype individually:
Bird.prototype.numLegs = 2;
This becomes tedious after more than a few properties.
Bird.prototype.eat = function() {
console.log(“nom nom nom”);
}
Bird.prototype.describe = function() {
console.log(“My name is “ + this.name);
}
Use object sintax to set all new prototype properties of the constructor.
function Dog(name) { this.name = name; }
Dog.prototype = {
constructor: Dog, // this is important to avoid undefined constructor of Dog!
numLegs: 2,
eat: () => { console.log(‘nom nom nom’); },
describe: () => { console.log(My name is ${this.name}
); }
};
Understand Where an Object’s Prototype Comes From
Just like people inherit genes from their parents, an object inherits its prototype directly from the constructor function that created it. For example, here the Bird constructor creates the duck object:
function Bird(name) { this.name = name; }
let duck = new Bird("Donald"); duck inherits its prototype from the Bird constructor function. You can show this relationship with the isPrototypeOf method:
Bird.prototype.isPrototypeOf(duck); // returns true
Use isPrototypeOf to check the prototype of beagle.
function Dog(name) { this.name = name; }
let beagle = new Dog(“Snoopy”);
console.log(Dog.prototype.isPrototypeOf(beagle));
How the Prototype Chain Works ?
Object Oriented Programming: Understand the Prototype Chain
All objects in JavaScript (with a few exceptions) have a prototype. Also, an object’s prototype itself is an object.
function Bird(name) { this.name = name; }
typeof Bird.prototype; // => object
Because a prototype is an object, a prototype can have its own prototype! In this case, the prototype of Bird.prototype is Object.prototype:
Object.prototype.isPrototypeOf(Bird.prototype); // returns true How is this useful? You may recall the hasOwnProperty method from a previous challenge:
let duck = new Bird("Donald"); duck.hasOwnProperty("name"); // => true The hasOwnProperty method is defined in Object.prototype, which can be accessed by Bird.prototype, which can then be accessed by duck. This is an example of the prototype chain.
In this prototype chain, Bird is the supertype for duck, while duck is the subtype. Object is a supertype for both Bird and duck.
Object is a supertype for all objects in JavaScript. Therefore, any object can use the hasOwnProperty method.
Heres an exemple in practice:
function Dog(name) { this.name = name; }
let beagle = new Dog(“Snoopy”);
Dog.prototype.isPrototypeOf(beagle); // => true
console.log(Object.prototype.isPrototypeOf(Dog.prototype)); // => true
Show an example of principle DRY(Don’t Repeat Yourself).
There’s a principle in programming called Don’t Repeat Yourself (DRY). The reason repeated code is a problem is because any change requires fixing code in multiple places. This usually means more work for programmers and more room for errors.
Notice in the example below that the describe method is shared by Bird and Dog:
Bird.prototype = { constructor: Bird, describe: function() { console.log("My name is " + this.name); } };
Dog.prototype = {
constructor: Dog,
describe: function() {
console.log(“My name is “ + this.name);
}
};
The describe method is repeated in two places. The code can be edited to follow the DRY principle by creating a supertype (or parent) called Animal:
function Animal() { };
Animal.prototype = {
constructor: Animal,
describe: function() {
console.log(“My name is “ + this.name);
}
};
Since Animal includes the describe method, you can remove it from Bird and Dog:
Bird.prototype = {
constructor: Bird
};
Dog.prototype = {
constructor: Dog
};
How to Inherit Behaviors from a Supertype ?
Object.create(obj) creates a new object, and sets obj as the new object’s prototype. Recall that the prototype is like the “recipe” for creating an object. By setting the prototype of animal to be Animal’s prototype, you are effectively giving the animal instance the same “recipe” as any other instance of Animal.
For example:
// Creates a supertype function Animal() { }
Animal.prototype = { constructor: Animal, eat: function() { console.log("nom nom nom"); } };
//Inherits behavior from Animal (supertype) function Dog() { }
Dog.prototype = Object.create(Animal.prototype);
let beagle = new Dog(); beagle.eat();
How to Reset an Inherited Constructor Property ?
function Animal() { } function Bird() { } function Dog() { }
//Sets prototype of Animal. This sets constructor of this //objects of Animal
Bird.prototype = Object.create(Animal.prototype); Dog.prototype = Object.create(Animal.prototype);
//Here resets constructor of objects inherited from //Animal to your own constructor
Bird.prototype.constructor = Bird; Dog.prototype.constructor = Dog;
let duck = new Bird(); let beagle = new Dog();
What is the difference between instantiate objects with operator new and Object.create() method ?
Need answer.
Give an example of how to add methods in objects after inherit prototype for another object.
// Creates Object Animal and its your prototype. function Animal() { } Animal.prototype.eat = function() { console.log("nom nom nom"); };
//Creates Object function Dog() { }
//inherits from Dog prototype Dog.prototype = Object.create(Animal.prototype);
//sets Dog constructor to Dog Dog.prototype.constructor = Dog;
//sets method bark to the prototype of Dog Dog.prototype.bark = () => { cDonsole.log('Woof!'); };
let beagle = new Dog();
beagle. eat(); // Should print “nom nom nom”
beagle. bark(); // Should print “Woof!”
Give an example of how to override a method inherited from an Object.
// Creates a Bird Object function Bird() { }
//Sets prototype Bird a function fly Bird.prototype.fly = function() { return "I am flying!"; };
//Creates a Penguin Object with prototype of Bird. Then //sets its constructor to Penguin
function Penguin() { } Penguin.prototype = Object.create(Bird.prototype); Penguin.prototype.constructor = Penguin;
//Override Bird method in Penguin Object Penguin.prototype.fly = () => { return "Alas, this is a flightless bird."; };
let penguin = new Penguin(); console.log(penguin.fly());
Use a Mixin to Add Common Behavior Between Unrelated Objects
Inheritance is a powerful way to get behavior from Objects. However, in some cases, isn’t best solution. Show an exemple to add common behavior between unrelated objects.
let bird = { name: "Donald", numLegs: 2 };
let boat = { name: "Warrior", type: "race-boat" };
let glideMixin = (obj) => { obj.glide = () => { console.log("Glyding, Whoo Hoo!"); } };
glideMixin(bird);
glideMixin(boat);
bird. glide();
boat. glide();
Use Closure to Protect Properties Within an Object from Being Modified Externally
Give an example in we can externally acesses property value from an Object without externally changes the value from that property.
function Bird() { // acessed only in Bird scope let weight = 15;
// acessed externally this.getWeight = () => { return weight; }; }
let eagle = new Bird(); console.log(eagle.getWeight());
how does the IIFE standard work and what is its importance and common usage in Javascript? Show an example.
An immediately invoked function expression (IIFE) is often used to group related functionality into a single object or module. For example, an earlier challenge defined two mixins:
let funModule = (function (){ return { singMixin: function (obj) { obj.sing = function() { console.log("Singing to an awesome tune"); } }, isCuteMixin: function(obj) { obj.isCute = function() { return true; }; } } })(); This wrap both functions using isCuteMixin and singMixin so that we can access it from funModule:
console. log(funModule.isCuteMixin(//pass an object));
console. log(funModule.singMixin(//pass an object))