Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Object Oriented Programming Challenges #15

Closed
26 tasks done
QuincyLarson opened this issue Jul 4, 2016 · 64 comments
Closed
26 tasks done

Object Oriented Programming Challenges #15

QuincyLarson opened this issue Jul 4, 2016 · 64 comments

Comments

@QuincyLarson
Copy link
Contributor

QuincyLarson commented Jul 4, 2016

@utsab is in charge of coordinating the expansion of these challenges, but he needs your help.

For each challenge, please reply to this GitHub issue with:

  1. Challenge description text
  2. Test suite (using the assert method)
  3. The seed code, which is pre-populated in the editor at the beginning of the challenge
  4. A working solution that makes all tests pass

Here are the challenges we have currently planned (these can be further expanded):

Objects

  • Create a basic JavaScript object.
  • Use dot notation to access object’s properties.
  • Create a method on an object.
  • Make code more reusable with “this”.

Constructors

  • Define a Constructor Function
  • Use a Constructor to Create Objects
  • Extend Constructors to Receive Arguments
  • Verify an Object's Constructor with instanceof

Prototypes

  • Understand "own" properties
  • Use prototype properties to reduce duplicate code
  • Iterate over all properties
  • Understand the "constructor" property
  • Change the prototype to a new object
  • Remember to set the "constructor" property when changing the prototype
  • Understand where an object’s prototype comes from
  • Understand the prototype chain

Inheritance

  • Don’t Repeat Yourself
  • Inherit behaviors from a supertype
  • Use Inheritance in Constructor Functions
  • Reset the Inherited Constructor Property
  • Add Methods After Inheritance
  • Override Inherited Methods

Other

  • Use a Mixin to add common behavior between unrelated objects
  • Use closure to protect properties within an object from being modified externally.
  • Understand the immediately invoked function Expression (IIFE)
  • Use an IIFE to create a module

Here are the challenges as we originally discussed for archival purposes:

  • Declare JavaScript objects as variables #old
  • Constructors
    • Construct JavaScript objects with functions #old
    • Make instances of objects with constructor functions #old
    • Use instanceof to show the type of an object created with a constructor
    • constructor property of an instance also shows the type of an object
    • Make unique objects by passing in parameters to constructor #old
  • More on this
    • Every function gets a variable this ==> context in which the function was called. Illustrate with exercise.
    • this can refer to the global context. Illustrate with exercise
    • this can refer to a specific object. Illustrate with exercise
    • Explicitly set "this" with the "call", "apply", "bind" methods
    • use strict
  • Prototypes
    • Convert constructor-defined methods, "setGear" and "getGear" to prototype methods. (Explain that two "Bike" instances have the exact same method "setGear" ==> duplicate code ==> prototypes can help eliminate the duplicate code.)
    • Properties defined on prototype are available to all instances. Illustrate with exercise.
    • prototype properties vs. "own" properties
    • Iterate over all properties of an object
    • Iterate over all "own" properties of an object (using hasOwnProperty)
    • Iterate over all prototype properties of an object
    • Is the "constructor" property an "own" property or prototype property? Find out.
    • If instance sets its "own" property, it overrides the prototype's property
  • Prototypes with Constructors
    • Every object has a prototype property, including functions. A constructor function has its own prototype property. Illustrate with exercise.
    • When you create an object using new, the constructor's prototype property is assigned to the object instance's prototype. Exercise ==> print out the instance's "prototype" property
    • Changing a prototype affects all instances
    • Modify a built-in object's prototype, like Array. (Explain why this is not a good idea in production).
    • The constructor's prototype property is created with a "constructor" property equal to the function.
  • Inheritance
    • Objects inherit behavior from other objects via prototype chaining. A prototype chain occurs when one object's prototype is set to another object. Since the prototype itself is an object, it has its own prototype.
    • Objects automatically inherit from Object
    • Introduce concepts subtype and supertype
    • Use instanceof to show that an object is an instance of subtype and supertype
    • Show example where the subtype sets its prototype equal to an instance of the supertype
    • Show that you have to manually set the constructor property to the subtype
    • Calling supertype methods ===> use [SuperTypeName].call and pass in this
    • The obj.prototype is not obj's prototype.
  • Encapsulation (Data hiding)
    • Module pattern for creating private members ===> Immediately invoked function expression (IIFE)
    • Closure
    • Modules are great for single objects. Similar pattern for constructed objects. Reuse "Make object properties private" to show how to make private members within a constructor. #old
    • The underscore before name convention
  • Other
    • Prototypal chaining is not the only way to inherit behavior. ===> mixins
    • Various exercises to manipulate Arrays and Strings #old
@utsab
Copy link

utsab commented Jul 14, 2016

I'm willing to take this on as the project owner.

@QuincyLarson
Copy link
Contributor Author

@utsab awesome! Yes - we need to expand this. First things first, could you create a list of challenge titles? OOP is probably complicated enough that we could have 20 or 30 challenges associated with it.

@QuincyLarson
Copy link
Contributor Author

@utsab I've promoted you to topic owner.

@utsab
Copy link

utsab commented Jul 18, 2016

@QuincyLarson yes, I'll compile a list of challenge titles. I'll try to have this done by Wednesday.

@utsab
Copy link

utsab commented Jul 21, 2016

Here's a 1st draft of the topics for OOJS. (The pre-existing challenges are marked with hash tag #old):

  • Declare javascript objects as variables #old

Constructors

  • Construct javascript objects with functions #old
  • Make instances of objects with constructor functions #old
  • Use "instanceof" to show the type of an object created with a constructor.
  • "constructor" property of an instance also shows the type of an object
  • Make unique objects by passing in parameters to constructor #old

More on "this"

  • Every function gets a variable "this" ==> context in which the function was called. Illustrate with exercise.
  • "this" can refer to the global context. Illustrate with exercise.
  • "this" can refer to a specific object. Illustrate with exercise.
  • Explicitly set "this" with the "call", "apply", "bind" methods

Prototypes

  • Convert constructor-defined methods, "setGear" and "getGear" to prototype methods. (Explain that two "Bike" instances have the exact same method "setGear" ==> duplicate code ==> prototypes can help eliminate the duplicate code.)
  • Properties defined on prototype are available to all instances. Illustrate with exercise.
  • prototype properties vs. "own" properties.
  • Iterate over all properties of an object
  • Iterate over all "own" properties of an object
  • Iterate over all "prototype" properties of an object
  • Is the "constructor" property an "own" property or "prototype" property? Find out.
  • If instance sets its "own" property, it overrides the prototype's property

Prototypes with Constructors

  • Every object has a prototype property, including functions. A constructor function has its own "prototype" property. Illustrate with exercise.
  • When you create an object using "new", the constructor's prototype property is assigned to the object instance's prototype. Exercise ==> print out the instance's "prototype" property
  • Changing a prototype affects all instances
  • Modify a built-in object's prototype, like Array. (Explain why this is not a good idea in production).
  • The constructor's prototype property is created with a "constructor" property equal to the function.

Inheritance

  • Objects inherit behavior from other objects via prototype chaining. A prototype chain occurs when one object's prototype is set to another object. Since the prototype itself is an object, it has its own prototype.
  • Objects automatically inherit from "Object"
  • Introduce concepts "subtype" and "supertype"
  • Use "instanceof" to show that an object is an instanceof subtype and supertype.
  • Show example where the "subtype" sets its prototype equal to an instance of the supertype. Show that you have to manually set the "constructor" property to the subtype.
  • Calling supertype methods ===> use [SuperTypeName].call and pass in "this"

Encapsulation (Data hiding)

  • Module pattern for creating private members ===> Immediately invoked function expression (IIFE)
  • Closure
  • Modules are great for single objects. Similar pattern for constructed objects. Reuse "Make object properties private" to show how to make private members within a constructor. #old

Other

  • Prototypal chaining is not the only way to inherit behavior. ===> mixins
  • Various exercises to manipulate Arrays and Strings #old

Looking forward to hearing your feedback @QuincyLarson and anyone else who would like to discuss.

@alayek
Copy link
Member

alayek commented Jul 22, 2016

@utsab I am interested! It's midday in India now, and maybe we can have a call tonight? I will also update the list above which started this thread, with your list.

You can reach me via gitter

@utsab
Copy link

utsab commented Jul 22, 2016

@alayek, great! Glad to have your help on this. I messaged you on gitter about setting up a time to chat.

@QuincyLarson
Copy link
Contributor Author

@utsab Thanks for your patience with my slow response.

This is an excellent list of OOP concepts! I am so excited about this. We will finally give OOP the level of detail it deserves.

Let me know if I can be of any help with designing these challenges, their descriptions, and tests. I will look forward to seeing them here as you have time to add them :)

@user512
Copy link

user512 commented Jul 31, 2016

@utsab Thanks for the call.
I will be working on Prototypes and Prototypes with Constructors as discussed.

@venture-vin
Copy link

venture-vin commented Aug 1, 2016

@utsab great talking with you! I will take on Mixins and Encapsulation (Data hiding).
Will post final solutions after the team review :)

@femmestem
Copy link

@utsab Great talk, thanks for onboarding me. As discussed, I will be covering Inheritance.

@alookatommorow
Copy link

@utsab Thanks for chatting, glad to be contributing! I am going to cover Constructors.

@arielsilvestri
Copy link

@utsab Great to be helping! We made a bit of a change to the curriculum and created an Objects section, which I'll be working on.

@arielsilvestri
Copy link

arielsilvestri commented Aug 8, 2016

Hey Quincy! I'll be posting my challenges now. We went ahead and made a basic Objects section that we'll need to update the original curriculum list to include.

Challenge Name: Introduction to Objects

Challenge

Create a basic JavaScript object.

Challenge Description

Think about things we encounter in our everyday life, like cars, shops, and birds. These are all objects: tangible things we 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. It's important to note that cars might all have wheels, but not all cars will have the same number of wheels.

We can use objects in JavaScript to model real-world objects, endowing them with properties and behavior just like their real-world counterparts. We’ll use the previous concepts to create a “duck” object:

var duck = {
  name: "Aflac",
  numLegs: 2
} 

We created a “duck” object with two property/value pairs: a name of Aflac and a numLegs of 2.

Instructions

Create a “dog” object with name and numLegs properties, and set them to a string and a number, respectively.

Challenge Seed

var dog = {
  //Your code here
}

Challenge Tests

Test to verify that the dog object is defined.
assert(typeof(dog) === “object”), ‘message: Dog should be an object.’;

Test to verify that the dog object has name and numLegs properties.
assert(typeof(dog.name) === ‘string’), ‘message: dog.name should be a string;
assert(typeof(dog.numLegs) === ‘number’), ‘message: dog.numLegs should be a number;

Challenge Solution

var dog = {
  name: //string,
  numLegs: //number
}

@arielsilvestri
Copy link

arielsilvestri commented Aug 8, 2016

Challenge Name: Accessing Properties on Objects

Challenge

Use dot notation to access object’s properties.

Challenge Description

Great job on defining that “dog” object. Now that we have created an object, let's talk about accessing some of these properties!

It's very simple to access the values of a property on an object. See the following example:

var duck = {
  name: "Aflac",
  numLegs: 2
} 

console.log(duck.name)
//This will print "Aflac" to the console. 

By using our object name, duck, along with the property whose value we want to utilize, color, we access the property of your object.

Instructions

Print the properties of the Dog object below to your console.

Challenge Seed

var dog = {
  name: “Spot”,
  numLegs: 4
}

//Add your two console calls here.

Challenge Tests

Test to see that the Dog’s name prints to the console.
assert(console.log(dog.name) === “Spot”), ‘message: console.log(dog.name) should print out “Spot”

Test to see that the Dog’s numLegs prints to the console.
assert(console.log(dog.numLegs) === 4), ‘message: console.log(dog.numLegs) should print out the number 4.’

Challenge Solution

var dog = {
  name: “Spot”,
  numLegs: 4
}

console.log(dog.name);
console.log(dog.numLegs);

@arielsilvestri
Copy link

arielsilvestri commented Aug 8, 2016

Challenge Name: JavaScript Object Methods

Challenge

Create a method on an object.

Challenge description

Now that we know how to create an object and access its properties, let's explore a special property of objects. Namely, we will talk about adding a method to our existing objects!

Methods are properties that are functions. We can do all sorts of things with these methods. Let's look at the previous duck example, and add a method:

var duck = {
  name: "Aflac",
  numLegs: 2
  sayName: function() {return "The name of this duck is " + duck.name + "."}
} 

duck.sayName();
//This will return "The name of this duck is Aflac."

As you can see above, we added the sayName method, which is a function that we can call to return a sentence telling us the color of the duck. This is a straightforward method of adding a method to an object in JavaScript.

Notice that we access the name of the duck in the method. We'll get back to that in the next lesson, but for now, this is the way we will insert that value into the string.

Instructions

In the following exercise, draw upon the previous “dog” object you created, and give it a method sayLegs. This method should return a sentence that says "This dog has 4 legs."

Challenge Seed

var dog = {
  name: “Spot”,
  numLegs: 4
  //Add your method here.
}

dog.sayLegs();

Challenge Tests

Test to see if the Dog object has a sayLegs method that returns the desired string.
assert(typeof(dog.sayLegs() === ‘function’), ‘message: dog.sayLegs() should be a function.’
assert(dog.sayLegs() === “This dog has 4 legs.”), ‘message: dog.sayLegs() should return the desired string.’

Challenge Solution

var dog = {
  name: “Spot”,
  numLegs: 4
  sayLegs: function() {return "This dog has " + dog.legs + " legs."}
}

dog.sayLegs();

@arielsilvestri
Copy link

arielsilvestri commented Aug 8, 2016

Challenge Name: Introducing "This"

Challenge

Make code more reusable with “this”.

Challenge Description

We are going to look at our sayName method from the previous example

  sayName: function() {return "The name of this duck is " + duck.name + "."}

Notice how we are referencing the variable name of our object, duck inside the sayName method in order to access the name property. While this is a totally valid way to access our object's property, there is a bit of a pitfall here.

What if the variable name of our object changes? What if, instead of a duck, it's a mallard now? Well, we would have to change duck.name to mallard.name. In this small example, that's fine, but what happens when we have an object that makes many references to its properties throughout its methods? Now the process gets much more complex!

There's a way to avoid that all. Introducing...this:

var duck = {
  name: "Aflac",
  numLegs: 2,
  sayName: function() {return "The name of this duck is " + this.name + "."}
} 

This is a very robust topic that would be a great idea to research more deeply. For now, understand that this, in the current context, refers to the object that our method is associated with: duck.

Now, if we changed our object's name to mallard, we don't have to find all our references to duck in our code. We've made our code more reusable and easy to read.

Instructions

Modify the dog.sayLegs method to remove any references to dog. It should follows the same code style as the duck object.

Challenge Seed

var duck = {
  name: "Aflac",
  numLegs: 2,
  sayName: function() {return "The name of this duck is " + this.name + "."}
}; 


// Modify code below this line. 

var dog = {
  name: “Spot”,
  numLegs: 4,
  sayLegs: function() {return "This dog has " + dog.numLegs + " legs."}
}; 

dog.sayLegs();

Challenge Tests

Test to see if dog.sayLegs() still returns the desired string.
assert(dog.sayLegs() === “This dog has 4 legs.”), ‘message: dog.sayLegs() should return the desired string.’

Challenge Solution

var dog = {
  name: “Spot”,
  numLegs: 4,
  sayLegs: function() {return "This dog has " + this.numLegs + " legs."}
}

dog.sayLegs();

@venture-vin
Copy link

venture-vin commented Aug 9, 2016

Challenge - 1

Use a Mixin to add common behavior between unrelated objects

What is a Mixin

As you have previously seen you can share behaviour through inheritance, but there are cases when inheritance is not the best solution. Inheritance does not work well for unrelated objects like Bird and Airplane. They can both fly, but a Bird is not a type of Airplane and vice versa.

For unrelated objects, it's better to use mixins. A mixin allows a collection of functions to be used by other objects.

var flyMixin = function(obj) {
    obj.fly = function() {
        console.log("Flying, wooosh!")
    }
}

The flyMixin takes any object and gives it the fly method.

var bird = {
    name: “Donald”,
    numLegs: 2,  
}

var plane = {
    model: “777”,
    numPassengers: 524 
}

flyMixin(bird); 
flyMixin(plane); 

Here bird and plane are passed into flyMixin, which then assigns the fly function to each object. Now bird and plane can both fly.

bird.fly(); //results in output on the screen: Flying, wooosh!
plane.fly(); //results in output on the screen: Flying, wooosh!

Note how the mixin allows for the same fly method to be reused by completely unrelated objects bird and plane.

Instructions

Create a mixin named glideMixin’ that defines a method namedglide. Use theglideMixinto give bothbirdandboatthe ability toglide`.

Challenge Seed

var bird = {
    name: ‘Donald’, 
    numLegs: 2,  
} 

var boat = {
    name: 'Warrior', 
    type: 'race-boat',  
}

// Only add code below this line.

Challenge Tests

assert(/var glideMixin = function(.+)/.test(code), ‘message: Please use the `var glideMixin` and set it equal to an anonymous function’
assert(typeof glideMixin === "function", ‘message: `glideMixin` should follow the proper structure of a function)
assert(/glideMixin\(.+\)/.test(code), ‘message: Don’t forget to pass the object to your mixin, to give it access to `.glide` method’

Challenge Solution

var glideMixin = function(obj) {
    obj.glide = function() {
        console.log("Gliding on the water")
    }
}

glideMixin(bird); 
glideMixin(boat); 

@venture-vin
Copy link

venture-vin commented Aug 9, 2016

Challenge - 2

Use closure to protect properties within an object from being modified externally.

Introduction to Private Properties

In the previous challenge, bird had a public property name. We say it is public because it can be changed outside of the context of bird.

bird.name = "Duffy"

Any part of your code can therefore easily change the name of bird to any value. Think about things like passwords and bank accounts being easily changeable by any part of your codebase. That could be catastrophic.

The simplest way to make properties private is by creating a var within the constructor function. In this way the private properties can only be accessed and changed by privileged methods within the constructor.

function Bird() { 
  var hatchedEgg = 10; // private property

  this.getHatchedEggCount = function() { //publicly available method that a bird object can use
  return hatchedEgg();  
  }
}

ducky = new Bird(); 
ducky.getHatchedEggCount() //returns 10

Here getHachedEggCount is a privileged method, because it has access to the private variable hatchedEgg. This is possible because hatchedEgg is declared in the same context as getHatchedEggCount. In javascript a function always has access to the context in which it was created. This is called closure.

Instructions

Change the function in the text editor to make the weight parameter private.

Challenge Seed

// rewrite the function below
function Bird() {
  this.weight = 15; 
}

Challenge Tests

assert(/var weight/.test(code), 'message: Please use the `var` before the weight to make it private'
assert(/function handleWeight\(\) {/.test(code), 'message: Please make sure to create a named function within your Bird object' 
assert(/return weight;/.test(code), 'message: Please remember to have a return statement for your private weight variable'
assert(/this.getWeight = function\(\) {/.test(code), 'message: Make sure to have a public method that an instance of your `Bird` can call on'

Challenge Solution

function Bird() { 
  var weight = 15; 
  function handleWeight() {
    return weight; 
  }
  this.getWeight = function() {
    return handleWeight();  
  }
}

Resources

https://curiosity-driven.org/private-properties-in-javascript
http://javascript.crockford.com/private.html

@venture-vin
Copy link

venture-vin commented Aug 9, 2016

Challenge - 3

Understand the immediately invoked function Expression (IIFE)

Challenge Description

A common pattern in javascript is to execute a function as soon as it is declared:

  (function () {
    console.log("Chirp, chirp!")
  })(); // this is the anonymous function expression that executes right away
// Outputs "Chirp, chirp" immediately

Note that the function has no name and is not stored in a variable. The two parentheses () at the end of the function expression cause it to be immediately executed or invoked. This pattern is known as an immediately invoked function expression or IIFE.

Instructions

Rewrite the function in the text editor to be an immediately invoked function expression (IIFE).

Challenge Seed

function makeNest() {
    console.log("A cozy nest is ready"); 
}

makeNest(); 

Challenge Tests

assert(/\(function\(\) {/.test(code), 'message: Make sure your new function is anonymous'
assert(/}\)\(\)/.test(code), 'message: Don’t forget to have double parentheses at the end of your function expression'

##Challenge Solution

(function() {
    console.log("A cozy nest is ready")
})(); 

@venture-vin
Copy link

venture-vin commented Aug 9, 2016

Challenge - 4

Use an IIFE to create a module

Challenge Description

An immediately invoked function expression (IIFE) is often used to group related functionality into a single object or module. For example, in a previous section, we defined two mixins:

function glideMixin(obj) {
      obj.glide = function() {
        console.log("Gliding on the water")
      }
}

function flyMixin(obj) {
      obj.fly = function() {
        console.log("Flying, wooosh!")
      }
}

We can group these mixins into a module as follows:

var motionModule = (function () {
  return {
    glideMixin: function (obj) {
      obj.glide = function() {
        console.log("Gliding on the water")
      }
    }, 
    flyMixin: function(obj) {
      obj.fly = function() {
        console.log("Flying, wooosh!")
      }
    }
  }
}) (); // The two parentheses cause the function to be immediately invoked

Note that we have an immediately invoked function expression (IIFE) whose sole purpose is to return an object. motionModule is this returned object. This returned object contains all of the mixin behaviors as properties on the object.

The advantage of the module pattern is that all of our motion behaviors can be packaged into a single object which can then be used by other parts of your code. Here we show a sample invocation:

motionModule.glideMixin(duck); 
duck.glide(); 

Instructions

Create a module named funModule to wrap the two mixins isCuteMixin and singMixin.

Challenge Seed

var isCuteMxin = function(obj) {
    obj.isCute = function() {
        return true
    }
}
var singMixin = function(obj) {
    obj.sing = function() {
        console.log("Singing to an awesome tune"); 
    }
}

Challenge Tests

assert(typeof funModule !== undefined, "message: <code>funModule</code> should be defined"); 
assert(funModule.isCuteMixin !== undefined, "message: <code>funModule.isCuteMixin</code> should be defined"); 
assert(funModule.singMixin !== undefined, "message: <code>funModule.singMixin</code> should be defined"); 

Challenge Solution

var funModule = (function () {
  return {
   isCuteMixin: function (obj) {
      obj.isCute = function() {
        return true
      }
    }, 
   singMixin: function(obj) {
      obj.sing = function() {
        console.log("Singing to an awesome tune")
      }
    }
  }
}) ();

@alayek
Copy link
Member

alayek commented Aug 9, 2016

@venture-vin @silvestrijonathan great work!

Could you please point which of the items in the roadmap these challenges point to? I will update the roadmap

@venture-vin
Copy link

@alayek - no problem did you want that in the beginning of each comment, and did you want general topics or the more specific topics? (Mine are Mixin & Data Encapsulation)

@alayek
Copy link
Member

alayek commented Aug 9, 2016

If you are adding challenges that are not mentioned in the roadmap, that's still fine. Just copy the roadmap and check off the item you are taking. Or copy it, add the item where it would fit in, and check it off.

I have updated one of the challenges you have submitted.

You wanted some help with how to introduce Closures without going into concepts of garbage collector etc. We can discuss if you are available.

@arielsilvestri
Copy link

@alayek, I'll go back and add those in after we discuss how we'll be adding them to the roadmap. Thanks!

@femmestem
Copy link

femmestem commented Aug 9, 2016

Inheritance

Challenge 3: Set the Child's Prototype to an Instance of the Parent

Updated: 08/24/16

Challenge

Challenge: Set the Child's Prototype to an Instance of the Parent

Challenge Description
In the previous challenge we showed step 1 for inheriting behavior from the supertype (or parent) Animal: making a new instance of Animal.

In this challenge, we cover the next step: set the prototype of the subtype (or child) -- in this case, Bird -- to be an instance of Animal.

Bird.prototype = Object.create(Animal.prototype);

What does that do for us? Remember that the prototype is like the "recipe" for creating an object. In a way, we are saying that the recipe for Bird includes an instance of Animal as a key ingredient.

var duck = new Bird("Donald"); 
duck.eat(); // prints "nom nom nom"

duck inherits all of Animal's properties including the eat method.

Instructions

Modify the code so that instances of Dog inherit from Animal.

Challenge Seed

function Animal() {

};

Animal.prototype = {
    constructor: Animal, 
    eat: function() {
        console.log("nom nom nom");
    }
}


function Dog() {

};

//
// Add code here
//

var beagle = new Dog();

beagle.eat();  //Should print "nom nom nom"

Challenge Tests
assert(Animal.prototype.isPrototypeOf(Dog.prototype), 'message: Dog.prototype should be an instance of Animal);

Challenge Solution

function Animal() {};
function Dog() {};

Animal.prototype.eat = function () { console.log("nom nom nom"); };

Bird.prototype = Object.create(Animal.prototype);

var beagle = new Dog();

beagle.eat(); // prints "nom nom nom"

@femmestem
Copy link

femmestem commented Aug 9, 2016

Inheritance

Challenge 2: Inherit Behaviors From A Supertype

Updated: 08/22/16

Challenge
Inherit Behaviors From A Supertype

Challenge Description

In the previous challenge, we created a supertype called Animal that defined behaviors shared by all animals:

function Animal() { };

Animal.prototype.eat = function()  {
console.log("nom nom nom");
}

In this and the next challenges, we will learn how to reuse Animal's methods inside Bird and Dog without defining them again by using a technique called inheritance.

This challenge will cover the first step: make an instance of the supertype (or parent).

We already know one way to create an instance of Animal using the new operator:

var animal = new Animal();

There are some disadvantages when using this syntax for inheritance, which are too complex for the scope of this challenge. Instead, we show a better approach:

var animal = Object.create(Animal.prototype);

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, we are effectively giving animal the same "recipe" as any other instance of Animal.

animal.eat(); // prints "nom nom nom"
animal instanceof Animal; //=> true

Instructions

Use Object.create to make two instances of Animal named duck and beagle

Challenge Seed

function Animal(){

}

Animal.prototype = {
    constructor: Animal, 
    eat: function() {
        console.log("nom nom nom");
    }
}

// Modify the code below this line

var duck =  
var beagle = 

duck.eat(); // Should print "nom nom nom"
beagle.eat(); //Should print "nom nom nom" 

Challenge Tests
assert(typeof duck !== "undefined", 'message: Did you remember to define the variable duck?);
assert(typeof beagle !== "undefined", 'message: Did you remember to define the variable beagle?);

assert(duck instanceof Animal, 'message: Did you remember to assign the Animal prototype to duck?')
assert(beagle instanceof Animal, 'message: Did you remember to assign the Animal prototype to beagle?')

Challenge Solution

function Animal(){

}

Animal.prototype = {
    constructor: Animal, 
    eat: function() {
        console.log("nom nom nom");
    }
}

// Modify the code below this line

var duck =  Object.create(Animal.prototype); 
var beagle = Object.create(Animal.prototype); 

duck.eat(); // Should print "nom nom nom"
beagle.eat(); //Should print "nom nom nom" 

@femmestem
Copy link

femmestem commented Aug 9, 2016

Inheritance

Challenge 5: Add Own Methods To Inherited Prototype

Updated: 08/22/16

Challenge
Add Own Methods To Inherited Prototype

Challenge Description
A constructor function that inherits its prototype object from a super-type constructor function can still have its own methods in addition to inherited methods.

Let's use Bird for example, a constructor that inherits its prototype from Animal.

function Animal() {}
Animal.prototype.eat = function () { console.log("Nom nom nom"); };

function Bird() {}
Bird.prototype = Object.create(Animal.prototype);
Bird.prototype.constructor = Bird;

In addition to what is inherited from Animal, we want to add behavior that is unique to birds. Let’s give Bird a fly() function. we add a function to Bird's protoype the same way we do with any constructor function: Bird.prototype.fly = function () { console.log("I'm flying!"); };

Now instances of Bird will have both eat() and fly() methods.

var duck = new Bird;
duck.eat(); // prints "Nom nom nom"
duck.fly(); // prints "I'm flying!"

Instructions
Add the necessary code to make beagle respond to eat() and bark().

Hint
Objects inherit methods from other objects by cloning their prototype. The Object.create method will come in handy, and don't forget to reset the constructor property afterward!

Challenge Seed

function Animal(){};
Animal.prototype.eat = function () { console.log("Nom nom nom"); };

function Dog() {};

// Add code below this line

// Add code above this line

var beagle = new Dog;

beagle.eat(); // prints "Nom nom nom"
beagle.bark(); // prints "Woof!"

**Challenge Tests**
assert(typeof Animal.prototype.bark == "undefined", 'message: Only instances of Dog should respond to the .bark() method');

assert(!(typeof Dog.prototype.eat == "undefined"), 'message: Dog should inherit the .eat() method from Animal');

assert(beagle instanceof Animal, 'message: Dog should inherit the .eat() method from Animal');

assert(beagle.constructor === Dog, 'message: Did you remember to the constructor for Dog?');

**Challenge Solution**
```javascript
function Animal(){};
Animal.prototype.eat = function () { console.log("Nom nom nom"); };

function Dog() {};

// Add code below this line
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function () {};
// Add code above this line

var beagle = new Dog;

beagle.eat(); // prints "Nom nom nom"
beagle.bark();

@femmestem
Copy link

femmestem commented Aug 9, 2016

Inheritance

Challenge 6: Override Inherited Methods

Updated: 08/24/16

Challenge
Override Inherited Methods

Challenge Description
In previous lessons, we learned that an object can inherit its behavior (methods) from another object by cloning its prototype object, like this ChildObject.prototype = Object.create(ParentObject.prototype). We gave ChildObject its own methods by chaining them onto its prototype, like this ChildObject.prototype.methodName = function () {...}.

We can override an inherited method the same way by adding a method to ChildObject.prototype using the same method name as the one we want to override.

Here's an example of Bird overriding the eat() method inherited from Animal.

function Animal(){}

Animal.prototype.eat = function() { return "Nom nom nom"; };

function Bird(){}

// inherit methods first, followed by method overrides
Bird.prototype = Object.create(Animal.prototype);

// Bird.eat() overrides Animal.eat()
Bird.prototype.eat = function () { return "Peck peck peck"; };

If we have an instance var duck = new Bird and we call duck.eat(), here’s how JavaScript looks for the method on duck’s prototype chain:

  1. duck => Is eat() defined here? No.
  2. Bird => Is eat() defined here? => Yes. Execute it and stop searching.
  3. Animal => eat() is also defined here, but JavaScript stopped searching before reaching this level.
  4. Object => JavaScript stopped searching before reaching this level.

Instructions

Override the fly() method for Penguin so that it prints in the console "Alas, this is a flightless bird."

Challenge Seed

function Bird(){}

Bird.prototype.fly = function () { return "I'm flying!"; };

function Penguin(){}
Penguin.prototype = Object.create(Bird.prototype);
Penguin.prototype.constructor = Penguin;

// Only add code below this line

// Only add code above this line

var penguin = new Penguin;
console.log(penguin.fly());

Challenge Tests
assert(penguin.fly() === "Alas, this is a flightless bird.", 'message: penguin.fly() should return "Alas, this is a flightless bird."');

assert((new Bird).fly() === "I'm flying!", 'message: bird.fly() should return "I'm flying!"');

assert(penguin.constructor === Penguin, 'message: Did you remember to the constructor for Penguin?');

Challenge Solution

function Bird(){}

Bird.prototype.fly = function () { return "I'm flying!"; };

function Penguin(){}
Penguin.prototype = Object.create(Bird.prototype);
Penguin.prototype.constructor = Penguin;

// Only add code below this line
Penguin.prototype.fly = function () {
    return "Alas, this is a flightless bird.";
}
// Only add code above this line

var penguin = new Penguin;
console.log(penguin.fly());

@femmestem
Copy link

femmestem commented Aug 9, 2016

Inheritance

Challenge 4: Reset An Inherited Constructor Property

Updated 08/24/16

Challenge
Reset An Inherited Constructor Property

Challenge Description
When an object inherits its prototype from another object, it also inherits the super-type’s constructor property.

Example:

function Bird(){};
Bird.prototype = Object.create(Animal.prototype);
var duck = new Bird;
duck.constructor // function Animal(){...}

Uh oh! We want duck and all instances of Bird to show that they were constructed by Bird. We have to manually set Bird's constructor property to the Bird object, like this: Bird.prototype.constructor = Bird. Now, duck.constructor returns function Bird(){...}.

Instructions

Fix the code so duck.constructor and beagle.constructor return their respective constructors.

Challenge Seed

function Animal(){}
function Bird(){}
function Dog(){}

Bird.prototype = Object.create(Bird.prototype);
Dog.prototype = Object.create(Bird.prototype);

//
// Add code here
//

var duck = new Bird;
var beagle = new Dog;

Challenge Tests
assert(Animal.prototype.isPrototypeOf(Bird.prototype), 'message: Bird.prototype should be an instance of the Animal');

assert(duck.constructor === Bird, 'message: duck.constructor should return Bird');

assert(Animal.prototype.isPrototypeOf(Dog.prototype), 'message: Dog.prototype should be an instance of the Animal');

assert(beagle.constructor === Bird, 'message: beagle.constructor should return Dog');

Challenge Solution

function Animal(){}
function Bird(){}
function Dog(){}

Bird.prototype = Object.create(Animal.prototype);
Dog.prototype = Object.create(Animal.prototype);

Bird.prototype.constructor = Bird;
Dog.prototype.constructor = Dog;

var duck = new Bird;
var beagle = new Dog;

@QuincyLarson
Copy link
Contributor Author

@user512 Excellent work, Tom! These are coming along great. You do an excellent job of explaining these concepts, and these challenges are really well conceived.

@user512
Copy link

user512 commented Aug 23, 2016

Credit to @utsab. He is great at leading the team and teaching these concepts.

@utsab
Copy link

utsab commented Aug 23, 2016

Here is the final list of topics. Note that this is different than what is posted in the first comment. @alayek, can you please update the first comment with this new list? Thank you.

Objects

  • Create a basic JavaScript object.
  • Use dot notation to access object’s properties.
  • Create a method on an object.
  • Make code more reusable with “this”.

Constructors

  • Define a Constructor Function
  • Use a Constructor to Create Objects
  • Extend Constructors to Receive Arguments
  • Verify an Object's Constructor with instanceof

Prototypes

  • Understand "own" properties
  • Use prototype properties to reduce duplicate code
  • Iterate over all properties
  • Understand the "constructor" property
  • Change the prototype to a new object
  • Remember to set the "constructor" property when changing the prototype
  • Understand where an object’s prototype comes from
  • Understand the prototype chain

Inheritance

  • Don’t Repeat Yourself
  • Inherit behaviors from a supertype
  • Use Inheritance in Constructor Functions
  • Reset the Inherited Constructor Property
  • Add Methods After Inheritance
  • Override Inherited Methods
  • Call a supertype method

Other

  • Use a Mixin to add common behavior between unrelated objects
  • Use closure to protect properties within an object from being modified externally.
  • Understand the immediately invoked function Expression (IIFE)
  • Use an IIFE to create a module

The final version of all of these challenges is located in this google doc

@alayek
Copy link
Member

alayek commented Aug 23, 2016

@utsab yeah I was just about to update the first comment. Thanks!

@QuincyLarson
Copy link
Contributor Author

@utsab Excellent! Could you check the boxes that correspond to your created challenges so we can see which challenges remain to be created?

@femmestem
Copy link

femmestem commented Aug 24, 2016

Inheritance

Challenge 1: Don't Repeat Yourself

Challenge
Don't Repeat Yourself

Challenge Description
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, which 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 therefore repeated in two places. We can make our code more DRY 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, we can then remove it from Bird and Dog.

Bird.prototype = {
    constructor: Bird
};

Dog.prototype = {
    constructor: Dog
};

Instructions

The eat method is repeated in both Cat and Bear. Make the code more DRY by moving the eat method to the Animal supertype.

Challenge Seed

function Cat(name) {
    this.name = name; 
};

Cat.prototype = {
    constructor: Cat, 
    eat: function() {
        console.log("nom nom nom");
    }
};

function Bear(name) {
    this.name = name; 
};

Bear.prototype = {
    constructor: Bear, 
    eat: function() {
        console.log("nom nom nom");
    }
};


function Animal(){
};

Animal.prototype = {
    constructor: Animal
};

Challenge Tests

Test that Animal.prototype has the eat method.
Test that Bear.prototype does not have the eat method
Test that Cat.prototype does not have the eat method

Challenge Solution

function Cat(name) {
    this.name = name; 
};

Cat.prototype = {
    constructor: Cat
};

function Bear(name) {
    this.name = name; 
};

Bear.prototype = {
    constructor: Bear;
};

function Animal(){

};

Animal.prototype = {
    constructor: Animal, 
    eat: function() {
        console.log("nom nom nom");
    }
};

@utsab
Copy link

utsab commented Aug 26, 2016

@QuincyLarson, I updated the list of topics and checked off the completed challenges. Every challenge except one (calling a supertype method) was created.

Since there were a few people creating challenges for this topic, I went through everyone's challenges and updated them for stylistic consistency. The final version of all of these challenges is located in this google doc.

Is this an acceptable way to submit the final versions of the challenges?

@QuincyLarson
Copy link
Contributor Author

@utsab yes - this should work fine. Rather than asking you to manually port these over to GitHub, any time you have available would be better invested in helping design the remaining challenges: #46

Thanks again!

@QuincyLarson QuincyLarson mentioned this issue Sep 22, 2016
23 tasks
@HKuz
Copy link
Member

HKuz commented Oct 4, 2016

Hello @QuincyLarson @utsab and everyone else on this chain - I'm currently working on this section in the QA process and have a couple questions. Right now, these challenges are ordered to come after the ES6 section (see #46) and we've been converting the other new JS sections so their examples/seed code use ES6 syntax. (This is done for Regex and Debugging so far). Is this section replacing the current FCC Object Oriented section, or will it be layered with it? If it's replacing that section, should we convert this into ES6 syntax to be consistent? Given the new class syntax, does this materially change any of the challenges?

If we are converting to ES6 - I'm relatively new to using it, and would appreciate help to make sure the conversion is done correctly.

Let me know, thanks!

(Side note @QuincyLarson - this comment would also apply to the Functional Programming and the Advanced Data Structures sections as well)

@QuincyLarson
Copy link
Contributor Author

@HKuz we plan to completely eliminate the old OOP/FP section.

Another note on this: what we are teaching is not technically ES6 - it is ES2016, which is two generations ahead of ES6.

Me and @BerkeleyTrue's thinking is we should just merge the ES6 section into the JavaScript section and call it "JavaScript". Then we can use the latest syntax in all of our challenges.

I will do this once we finish the ES6 section. It shouldn't affect your QA process.

@HKuz
Copy link
Member

HKuz commented Oct 5, 2016

@QuincyLarson okay, thanks for clarifying. Makes sense to combine all the JS challenges together. I'll keep plugging on the QA process.

@QuincyLarson
Copy link
Contributor Author

@HKuz great - it's a plan 🙂 We can assume that all JavaScript-related challenges on FCC can use ES2016 syntax, then.

@utsab
Copy link

utsab commented Oct 7, 2016

@HKuz and @QuincyLarson, the original outline for the OOJS challenges does not factor in the ES6 "class" syntax. If we do emphasize the "class" syntax, then maybe we do not need the prototype-chain sections. With the new "class" syntax, we no longer need to use the prototype chain to implement inheritance.

@QuincyLarson
Copy link
Contributor Author

@utsab my understanding is that the "class" syntax is just syntactic sugar. These objects still use prototypical inheritance. Perhaps @BerkeleyTrue or @alayek could chime in here.

If this is the case, we could introduce the class keyword after we finish covering prototypes, and explain how it makes things more convenient.

@HKuz
Copy link
Member

HKuz commented Oct 7, 2016

@utsab et al - if you all do decide to add a new challenge, you can post it here and mention me. I'm almost through reviewing the others and adding a new one is not a problem. Just let me know where it would go in the order 😄 Thanks!

@HKuz
Copy link
Member

HKuz commented Oct 20, 2016

Hi folks - here's a first cut of the introductory text for this section. This is meant to be a standalone intro, but the following section is Functional Programming. That's why I included the language about different approaches to software development - I'm thinking it'll help transition between the sections and tie them together.

Any comments or suggestions are welcome 😄

Introduction to the Object Oriented Programming Challenges

At its core, software development solves a problem or achieves a result with computation. The software development process first defines a problem, then presents a solution. Object oriented programming is one of several major approaches to the software development process.

As its name implies, object oriented programming organizes code into object definitions. These are sometimes called classes, and they group together data with related behavior. The data is an object's attributes, and the behavior (or functions) are methods.

The object structure makes it flexible within a program. For example, objects can exchange information with each other. One object would invoke a method and send data to the other in a process called message passing.

Object oriented programming uses the concept of inheritance. It allows a new class to inherit, or receive, all the features from a base or parent class plus a few of its own. Inheritance helps to avoid repeated code by reusing it between related classes.

Your choice of programming approach depends on a few factors. The type of problem, and how you want to structure your data and algorithms make a difference. This section covers object oriented programming principles in JavaScript.

@QuincyLarson
Copy link
Contributor Author

@HKuz Excellent description. I would avoid using the word "invoke" here unless we've used it before this point. As with the other descriptions, I think this could ultimately be boiled down to just 2 or 3 paragraphs. It wouldn't be as comprehensive as this explanation is, but a lot more people would read the entire thing.

@HKuz
Copy link
Member

HKuz commented Oct 23, 2016

@QuincyLarson thanks for the feedback and apologies for the delayed response, I was on the road and my internet was all wonky this weekend from that ddos attack. I can rework this and get it in the next iteration of the feature/curriculum-expansion branch.

@QuincyLarson
Copy link
Contributor Author

@HKuz No need to apologize - I'm happy your receptive to making this small change. I hope you had a fun weekend on the road.

@alookatommorow
Copy link

@QuincyLarson how is it going with the new curriculum? Is there anything I can do to help?

@QuincyLarson
Copy link
Contributor Author

@alookatommorow thanks for your offer. We are getting quite close to pushing this to beta. Look for an announcement in the coming weeks. In the meantime, you can help hanging out on our forum and helping us QA some of the new projects we're designing by building them yourself: https://forum.freecodecamp.com/c/meta

@alookatommorow
Copy link

Ok, great. Thanks @QuincyLarson

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants