Object Oriented JavaScript

Remember objects syntax
var car = {
“wheels”:4,
“engines”:1,
“seats”:5
};
object attributes = properties
object functions = methods
Objects have their own attributes, called properties, and their own functions, called methods.
this keyword
We used the “this” keyword to reference public properties of the current object.
construct JS objects with functions

constructor function

var Car = function() {
this.wheels = 4;
this.engines = 1;
this.seats = 5;
};

We are also able to create objects using constructor functions.

A constructor function is given a capitalized name to make it clear that it is a constructor.

In a constructor the “this” variable refers to the new object being created by the constructor. So when we write,

this.wheels = 4;

inside of the constructor we are giving the new object it creates a property called wheels with a value of 4.

You can think of a constructor as a description for the object it will create.

make instances of objects with a constructor function

var Car = function() {
this.wheels = 4;
this.engines = 1;
this.seats = 5;
};

var myCar = new Car();
myCar.nickname = “Knutette”;

To use a constructor function we call it with the new keyword in front of it like:

var myCar = new Car();

myCar is now an instance of the Car constructor that looks like the object it described:

{
wheels: 4,
engines: 1,
seats: 5
}
Note that it is important to use the new keyword when calling a constructor. This is how Javascript knows to create a new object and that all the references to this inside the constructor should be referring to this new object.

*What about Object.create()? Difference between Object.create() and new???*

Now, once the myCar instance is created it can be used like any other object and can have its properties accessed and modified the same way you would usually. For example:

myCar.turboType = “twin”;

Our myCar variable now has a property turboType with a value of “twin”.

make unique objects by passing parameters to our constructor

var Car = function(wheels, seats, engines) {
this.wheels = wheels;
this.seats = seats;
this.engines = engines;
};

// pass arguments to constructor function
var myCar = new Car(3,1,2);

The constructor we have is great, but what if we don’t always want to create the same object?

To solve this we can add parameters to our constructor. We do this like the following example:

var Car = function(wheels, seats, engines) {
this.wheels = wheels;
this.seats = seats;
this.engines = engines;
};

Now we can pass in arguments when we call our constructor.

var myCar = new Car(6, 3, 1);

This code will create an object that uses the arguments we passed in and looks like:

{
wheels: 6,
seats: 3,
engines: 1
}

make object properties private

Example:
var Car = function() {
// this is a private variable
var speed = 10;

// these are public methods
this.accelerate = function(change) {
speed += change;
};

this.decelerate = function() {
speed -= 5;
};

this.getSpeed = function() {
return speed;
};
};

Example:
var Bike = function() {

// Only change code below this line.
var gear;

this.setGear = function(set) {
gear = set;
};

this.getGear = function() {
return gear;
};
};

We used the “this” keyword to reference public properties of the current object.

We can also create private properties and private methods, which aren’t accessible from outside the object.

To do this, we create the variable inside the constructor using the var keyword we’re familiar with, instead of creating it as a property of “this”.

This is useful for when we need to store information about an object but we want to control how it is used by outside code.

functional programming and callback functions
http://javascriptissexy.com/understand-javascript-callback-functions-and-use-them/
iterate over arrays with map method

var oldArray = [1, 2, 3];
var timesFour = oldArray.map(function(val){
return val * 4;
});
console.log(timesFour); // returns [4, 8, 12]
console.log(oldArray); // returns [1, 2, 3]

The map method is a convenient way to iterate through arrays.

The map method will iterate through every element of the array, creating a new array with values that have been modified by the callback function, and return it. Note that it does not modify the original array.

*Note: In the example to the left, the callback only uses the value of the array element (the val argument) but your callback can also include arguments for the index and array being acted on.

condense arrays with reduce method

Here is an example of reduce being used to subtract all the values of an array:

var singleVal = array.reduce(function(previousVal, currentVal) {
return previousVal – currentVal;
}, 0);

The array method reduce is used to iterate through an array and condense it into one value.

To use reduce you pass in a callback whose arguments are an accumulator (in this case, previousVal) and the current value (currentVal).

The accumulator is like a total that reduce keeps track of after each operation. The current value is just the next element in the array you’re iterating through.

reduce has an optional second argument which can be used to set the initial value of the accumulator. If no initial value is specified it will be the first array element and currentVal will start with the second array element.

Example:
var array = [4,5,6,7,8];
var singleVal = 0;

var singleVal = array.reduce(function(total, num) { return total + num }, 0);

Like a for loop through the array to sum indexes.
See: https://www.airpair.com/javascript/javascript-array-reduce

filter arrays with filter method

The following code is an example of using filter to remove array elements that are equal to five:

Note: We omit the second and third arguments since we only need the value

array = array.filter(function(val) {
return val !== 5;
});

The filter method is used to iterate through an array and filter out elements where a given condition is not true.

filter is passed a callback function which takes the current value (we’ve called that val) as an argument.

Any array element for which the callback returns true will be kept and elements that return false will be filtered out.

Example:
var oldArray = [1,2,3,4,5,6,7,8,9,10];
// return values less than 6
var newArray = oldArray.filter(function(val) { return val < 6; });

sort arrays with sort method

Here is an example of using sort with a compare function that will sort the elements from smallest to largest number:

var array = [1, 12, 21, 2];
array.sort(function(a, b) {
return a – b;
});

You can use the method sort to easily sort the values in an array alphabetically or numerically.

Unlike the previous array methods we have been looking at, sort actually alters the array in place. However, it also returns this sorted array.

sort can be passed a compare function as a callback. The compare function should return a negative number if a should be before b, a positive number if a should be after b, or 0 if they are equal.

If no compare (callback) function is passed in, it will convert the values to strings and sort alphabetically.

Example: Use sort to sort array from largest to smallest.
var array = [1, 12, 21, 2];
array.sort(function(a,b) { return b – a;});

reverse arrays with reverse method

var myArray = [1, 2, 3];
myArray.reverse();
// returns [3, 2, 1]

You can use the reverse method to reverse the elements of an array.

reverse is another array method that alters the array in place, but it also returns the reversed array.

concatenate arrays with concat method

Here is an example of concat being used to concatenate otherArray onto the end of oldArray:

newArray = oldArray.concat(otherArray);

concat can be used to merge the contents of two arrays into one.

concat takes an array as an argument and returns a new array with the elements of this array concatenated onto the end.

Example: concat concatMe array

var oldArray = [1,2,3];
var newArray = [];

var concatMe = [4,5,6];

newArray = oldArray.concat(concatMe);

split strings with split method

Here is an example of split being used to split a string at every s character:

var array = string.split(‘s’);

You can use the split method to split a string into an array.

split uses the argument you pass in as a delimiter to determine which points the string should be split at.

Example: split string into array of words

var string = “Split me into an array”;
var array = [];
array = string.split(” “); // split at the space

join strings with join method

The following is an example of using join to join all of the elements of an array into a string with all the elements separated by word and:

var veggies = [“Celery”, “Radish”, “Carrot”, “Potato”];
var salad = veggies.join(” and “);
console.log(salad); // “Celery and Radish and Carrot and Potato”

We can use the join method to join each element of an array into a string separated by whatever delimiter you provide as an argument.

Example: Use the join method to create a string from joinMe with spaces in between each element and assign it to joinedString.

var joinMe = [“Split”,”me”,”into”,”an”,”array”];
var joinedString = ”;
joinedString = joinMe.join(” “); // joined with a space

variable access (also known as scoping)
scopes and closures
*scopes*
lexical scopes
the regions in your source code where you can refer to a variable by name without getting access errors

create a new lexical scope when you define a function

global scope
can go across JS files
lexical scope in a function
you have a new lexical scope, but you can still access global scope variables and you can access variables defined within the function
scoping limitations
in JS, you can assign to variables you haven’t declared before (e.g. removing the var statement) – variable you add this way will be automatically added to the global scope
*don’t do this*

only { } curly brackets on a function define a scope

calling functions
call outside the function – with a nested function, you have to call the inner most function inside the other functions
execution context
‘in-memory scope” structures
When a program runs, it builds up storage systems for holding the variables and their values.
execution context v. lexical scope
execution context builds as code runs
lexical scope builds as code is typed
in-memory data stores
keeps track of all the variables available to different function objects

a new execution context should be created every time you run a function

for each lexical scope, there may be many in-memory scopes created during execution

key-value pairs
hero = “Gal”
newSaga = {ƒ}
in-memory scopes v. in-memory objects
*not the same thing* even though in-memory scopes look like key-value pairs

*there are many limits on your access to execution context
*many rules for objects are true for execution context
*BUT you can never mix and match the two in a program*

they live in different worlds that almost never interact

the execution context holds values for that run of the function-its output

when you run the function again, it there is a variable change somewhere, the output will change

building multiple execution scopes
interpreter looks up variable locally (scans it) first, then falls through to the next level scope up to global looking for a variable
*closures*
functions should have access to all the variables of all the scopes that surround it > So what’s a closure?
A closure is any function that somehow remains available after all those outer scopes have returned.
How can you retain access to a function *after* the function calls that created them returned?
1. passing to setTimeout
2. return function from the function
3. save function to a global variable
(function( ) { })
function object
– can be pushed to an array
for execution context
*a new context is always created in the same context as its function was defined in
Example of closure
var sagas= []:
var hero = aHero(); // hero = “Boy”
var newSaga = function() {
var foil = aFoil(); // foil = “Rat”
sagas.push(function() {
var deed = aDeed(); // deed = “Eyes”
log(hero+deed+foil);
});
};

newSaga();
sagas[0](); //returns “BoyEyesRat”
sagas[0](); // new deed = “Digs” // returns “BoyDigsRat”
newSaga(); // new foil = “ET”
sagas[0](); // new deed = “Pins” //returns “BoyPinsRat”
–why? deeds is created in first newSaga()
sagas[1](); // new deed = “Gets” // returns “BoyGetsET”
–why? deeds is created in second newSaga()

“this” keyword
or “parameter this”
in JS, the way of referring to the current object

parameter this behaves almost like a normal parameter
Two major differences
1. you don’t get to pick the name of the parameter
2. you bind them different (5 different ways to do this)

“this” in an identifier that gets a value bound to it, like a variable, but instead of explicitly stating its value, “this” gets bound to the correct object automatically

the rules for the correct binding resemble the rules for positional function parameters

remember, parameters are…
the words we see between parentheses in a function definition
what “this” keyword won’t be bound/refer to
var fn = function(a,b) {
log(this);
};

NOT 1. {ƒ} the function object this appears within
NOT 2. ? “a new instance of” a function this appears wtihin

var ob2 = {method: fn};
NOT 3. {} an object that happens to have that function as a property

var = obj {
var fn = function(a,b) {
log(this);
};
};
NOT 4. The function appears inside the curly braces of some object literal creating a new memory object

obj.fn(3,4);
NOT 5. an “execution context” or “scope” of that function call

what “this” keyword will refer too
*obj*.fn(3,4);
1. the object found to the *left of the dot where the containing function is called*
this is a parameter of a method
var fn = function (one, two) {
log (this, one, two);
};

var r = {}, g= {}, b = {};
r.method = fn;

r.method(g,b);
// returns {} {} {} where the first is r, the second is g, and third is b
*Note, it won’t log the string “r” but rather the value of the “r” variable.

It’s passing a third parameter by calling that function on the right side of a dot access for property look up. The value that appears to the left of the dot will automatically be given the name this inside the of that function invocation.

a call to
fn(g, b); //returns {} {} where the second is g and the third b

without a . we can expect some default value to get bound to “this”


Using .call(), we can assign any value we want to the global – we can pass in one extra value at the beginning of the argument list
fn.call(r, g, b);
*Note: the use .call() overrides the method access rules
if we had y = {};
r.method.call(y, g, b); //returns {} {} {} where the first one is y, not r

undefined
when no values are passed to a function in vacation (), the parameters get bound to the values undefined
rule for “this”
look for a dot and look to the left of that dot to find the value of this

*Only the moment of function call back influences how the parameter gets bound

setTime(r.method, 1000( {})
r will not be passed if it’s not called at the time of callback

instead pass it like this to pass properties
setTime(function() {r.method(g,b)}, 1000);

***callback functions
designed so that they will be invoked by the system you pass them to
new r.method(g,b);
returns a brand new object
log(this);
returns global
*prototype chains*
a mechanism for making objects that resemble other objects

it makes one object behave as if it has all the properties of the other object by delegating the failed lookup of the first object to the second object

property lookup

1-time property copying

ongoing lookup time delegation

Start with var gold = {a, 1};

— we want to copy it
var blue = extend( {}, gold);
— we want to not copy but link it to the gold object
var rose = Object.create(gold);
*This means that it is not a copy. Whenever a property cannot be found on rose, it uses gold as a source for fallback properties.
*This means properties that aren’t found on rose might be found on gold, and we’re telling it to look there.

object prototype
provides the shared properties of all objects in the entire system

helper functions (?)

constructor property
e.g.
.constructor()
*object decorator pattern*
code reuse
practice of writing generalized code that can be used to address a variety of similar goals
-don’t repeat yourself
decorator function
It’s job is to augment an object with the properties needed to be considered something (in this case a car).

var carlike function(obj, loc) {
obj.loc = loc;
return obj;
};

*common to use adjectives to name decorator functions

method calling syntax with dot access
functions are properties too, so we can look up a function as a property of some object before invoking it

obj.move = move

*functional classes*
class
a powerful form of functions that can be used to make lots of similar objects
decorator pattern code v. classes
The difference is that the class builds the object that it’s going to augment. The decorator instead accepts the object that it’s going to augment as an input.
to change decorator code to a class
1. remove the obj function parameter in favor of declaring a local variable
*give is a different name – a Capitalized noun (i.e. not an adjective) – to show this
Constructor function
the function of a class because they build objects
instances of the class
the objects that get returned from constructor functions
instantiating
when we call a constructor function in order to create an instance
functional class pattern
a function that produces instances of a class
functional class pattern with shared methods
aka functional shared patterns
place a function outside of constructor function and use “this” in that helper function

this.loc++;

this replaces obj because this function is being called as a method on objects created with Car.

Why? because then we don’t create a new function within the constructor function each time we call it

functions are capable of storing properties just like any other object
*prototypal classes*
object literal v. Object.create()
.prototype v. .method

.prototype ambiguity

.prototype.constructor

instanceof operator
*pseudoclassical patterns*
attempts to resemble the class systems from other languages by adding syntactic conveniences
keyword new

new Car(9);

our function will run in Constructor mode

In constructor mode, inserts some lines of operation into your code because JS knows you’ll need it (e.g. var and return)

*like* this.Object.create();
return this;

*superclass and subclass*
superclass
A superclass function will be creating a lot of similar objects.

It’s the superclass because other classes will use its output as a starting point for their functions.

E.g.
Car – superclass (car is a class in itself and doesn’t need a subclass to work)
Cop – subclass (this will be a cop car)
Citizen – subclass (this will be a citizen car)

*pseudoclassical subclasses*
.call()
the .call() method of any function allows us to run that function in exactly the context we want it to
Object.create()
do no use, for example, new Car()
enum data types
In computer programming, an enumerated type (also called enumeration, enum, or factor in the R programming language, and a categorical variable in statistics) is a data type consisting of a set of named values called elements, members, enumeral, or enumerators of the type.
*FROM CODEACADEMY*
*Review important concepts of objects*
method – constructor notation
a function associated with objects

function someObject() {
this.someMethod = function() {
};
}
Suppose we said var someObj = new someObject();. When we call someObj.someMethod(), the code between the curly brackets { } will run.
*Methods defined in both constructors and literal notation can take parameters

method – literal notation
var someObj = {
aProperty: value,
someMethod: function(some, params) { }
};
When we call someObj.someMethod(some, values);, the code between the curly brackets { } will run.
*Methods defined in both constructors and literal notation can take parameters
call a method
When that method is called, this.propertyName will always refer to the most recent value of propertyName.

var james = {
job: “programmer”,
married: false,
sayJob: function() {
// complete this method
console.log(“Hi, I work as a ” + this.job); //*this.job*
}
};

// james’ first job
james.sayJob();

// change james’ job to “super programmer” here
james.job = “super programmer”;

// james’ second job
james.sayJob();

retrieving property values

dot notation
someObj.propName;

bracket notation
someObj[“propName”];

An advantage of bracket notation is that we are not restricted to just using strings in the brackets. We can also use variables whose values are property names:

var someObj = {propName: someValue};
var myProperty = “propName”;
someObj[myProperty]; // same as someObj[“propName”];

Example:
var james = {
job: “programmer”,
married: false
};

// set to the first property name of “james”
var aProperty = “job”;

// print the value of the first property of “james”
// using the variable “aProperty”
console.log(james[aProperty]);

typeof

var someObject = {someProperty: someValue};
console.log( typeof someObject );

var anObj = { job: “I’m an object!” };
var aNumber = 42;
var aString = “I’m a string!”;

console.log( typeof anObj ); // should print “object”
console.log( typeof aNumber ); // should print “number”
console.log( typeof aString ); // should print “string”

hasOwnProperty
This lets us know if an object has a particular property. It returns true or false, based on whether an object has a certain property.

var myObj = {
// finish myObj
name: “name”
};

console.log( myObj.hasOwnProperty(‘name’) ); // should print true
console.log( myObj.hasOwnProperty(‘nickname’) ); // should print false

var suitcase = {
shirt: “Hawaiian”
};

Example
if (suitcase.hasOwnProperty(“shorts”)) {
console.log(suitcase.shorts);
} else {
suitcase.shorts = “cargo”;
}

for – in loop
*avoid*

get all properties of an object

var nyc = {
fullName: “New York City”,
mayor: “Bill de Blasio”,
population: 8000000,
boroughs: 5
};

for(var property in nyc) {
console.log(property);
}
// returns all property names

for – in loop
*avoid*

get all values of properties of an object

hint: dog.species = dog[“species”] = “bulldog”;
And if we say: var x = “species”;
then dog[x] = “bulldog”;
*we can use the variable name in bracket notation to get the property’s value

var nyc = {
fullName: “New York City”,
mayor: “Bill de Blasio”,
population: 8000000,
boroughs: 5
};

// write a for-in loop to print the value of nyc’s properties
for(var value in nyc) {
console.log(nyc[value]);
}

*Object-oriented programming (OOP)*
constructors and classes
When you make a constructor, you are in fact defining a new class.

A class can be thought of as a type, or a category of objects—kind of like how Number and String are types in JavaScript.

define a class
function Person(name,age) {
this.name = name;
this.age = age;
}

// Let’s make bob and susan, using our constructor
var bob = new Person(“Bob Smith”, 30);
var susan = new Person(“Susan Jordan”, 35);

What keeps track of what a given class can or can’t do? What a class has or doesn’t have?

prototype

That is the job of the prototype.

JavaScript automatically defines the prototype for class with a constructor.

Example of class and prototype

We know we can add methods to objects, and we add the bark method to buddy. Hit run and you will see one “Woof” printed when buddy barks. Notice what happens when we try to get snoopy to bark though. Even though snoopy is of the class Dog, he doesn’t know how to bark because only buddy had bark added as a method.

*Fix it so that snoopy can bark, add this code
snoopy.bark = function() {
console.log(“Woof”);
};

function Dog (breed) {
this.breed = breed;
}

// here we make buddy and teach him how to bark
var buddy = new Dog(“Golden Retriever”);
buddy.bark = function() {
console.log(“Woof”);
};
buddy.bark();

// here we make snoopy
var snoopy = new Dog(“Beagle”);
// we need you to teach snoopy how to bark here

// this causes an error, because snoopy doesn’t know how to bark!
snoopy.bark();

“Class tells us helpful information about objects, and you can think of an object as a particular instance of a class.”
For example, look at our Person class again in the console. We know that any Person will have a name and age, because they are in the constructor. This allows us to create a function like printPersonName, which will take a Person as an argument and print out their name. We know the function will work on any Person, because name is a valid property for that class.

function Person(name,age) {
this.name = name;
this.age = age;
}
// a function that prints the name of any given person
var printPersonName = function (p) {
console.log(p.name);
};

var bob = new Person(“Bob Smith”, 30);
printPersonName(bob);

// make a person called me with your name and age
// then use printPersonName to print your name
var me = new Person(“Josie”, 34);
printPersonName(me);

prototype

If you want to add a method to a class such that all members of the class can use it, we use the following syntax to extend the prototype:

className.prototype.newMethod = function() {
statements;
};

Instead of using buddy.bark to add the bark method to just the buddy object, we use Dog.prototype.bark.

Click run this time, and both buddy and snoopy can bark just fine! Snoopy can bark too even though we haven’t added a bark method to that object. How is this so? Because we have now changed the prototype for the class Dog. This immediately teaches all Dogs the new method.

function Dog (breed) {
this.breed = breed;
};

// here we make buddy and teach him how to bark
var buddy = new Dog(“golden Retriever”);
*Dog.prototype.bark* = function() {
console.log(“Woof”);
};
buddy.bark();

// here we make snoopy
var snoopy = new Dog(“Beagle”);
/// this time it works!
snoopy.bark();

inheritance

Whenever this *X is-a Y* relationship exists, there’s a good chance that we should be using inheritance.

inheritance allows one class to see and use the methods and properties of another class. You can think of it as a child being able to use his or her parent’s money because the child inherits the money.
Using prototype in a constructor class

*Note the method calls “this.name”

// create your Animal class here
var Animal = function (name, numLegs) {
this.name = name;
this.numLegs = numLegs;
};

// create the sayName method for Animal
Animal.prototype.sayName = function() {
console.log(“Hi my name is ” + this.name);
}

// provided code to test above constructor and method
var penguin = new Animal(“Captain Cook”, 2);
penguin.sayName();

Making a new constructor class from another constructor class

To say that Penguin inherits from Animal, we need to set Penguin’s prototype to be Animal.

*var Penguin = Animal;*

!! Should this be var penguin = Animal; ????

function Animal(name, numLegs) {
this.name = name;
this.numLegs = numLegs;
}
Animal.prototype.sayName = function() {
console.log(“Hi my name is ” + this.name);
};

// create a Penguin constructor here
var Penguin = Animal;

// create a sayName method for Penguins here
Penguin.prototype.sayName = function() {
console.log(“Hi my name is ” + this.name);
}

// our test code
var theCaptain = new Penguin(“Captain Cook”, 2);
theCaptain.sayName();

DRY principle
don’t repeat yourself
create a new instance of constructor class using inheritance

*Penguin.prototype = new Animal();*

// the original Animal class and sayName method
function Animal(name, numLegs) {
this.name = name;
this.numLegs = numLegs;
}
Animal.prototype.sayName = function() {
console.log(“Hi my name is ” + this.name);
};

// define a Penguin class
function Penguin(name) {
this.name = name;
this.numLegs = 2;
}

// set its prototype to be a new instance of Animal
Penguin.prototype = new Animal();

create a new object/instance of a constructor prototype class using inheritance

*var penguin = new Penguin(“Benedit Cumberbatch”);*

// the original Animal class and sayName method
function Animal(name, numLegs) {
this.name = name;
this.numLegs = numLegs;
}
Animal.prototype.sayName = function() {
console.log(“Hi my name is ” + this.name);
};

// define a Penguin class
function Penguin(name) {
this.name = name;
this.numLegs = 2;
}

// set its prototype to be a new instance of Animal
Penguin.prototype = new Animal();

// create an object named penguin variable
// note ORDER matters, this comes after the instance
var penguin = new Penguin(“Benedit Cumberbatch”);

penguin.sayName();

accessing info from on prototype class that waterfalls up to its constructor class

*console.log(emperor.numLegs);*

function Penguin(name) {
this.name = name;
this.numLegs = 2;
}

// create your Emperor class here and make it inherit from Penguin
function Emperor(name) {
this.name = name;
}

// create an “emperor” object and print the number of legs it has
Emperor.prototype = new Penguin();

var emperor = new Emperor(“Benedict”);

console.log(emperor.numLegs);

prototype chain
If JavaScript encounters something it can’t find in the current class’s methods or properties, it looks up the prototype chain to see if it’s defined in a class that it inherits from. This keeps going upwards until it stops all the way at the top: the mighty Object.prototype (more on this later). By default, all classes inherit directly from Object, unless we change the class’s prototype.
going up the prototype chain

EXAMPLE

// original classes
function Animal(name, numLegs) {
this.name = name;
this.numLegs = numLegs;
this.isAlive = true;
}
function Penguin(name) {
this.name = name;
this.numLegs = 2;
}
function Emperor(name) {
this.name = name;
this.saying = “Waddle waddle”;
}

// set up the prototype chain
Penguin.prototype = new Animal();
Emperor.prototype = new Penguin();

var myEmperor = new Emperor(“Jules”);

console.log( myEmperor.saying ); // should print “Waddle waddle”
console.log( myEmperor.numLegs ); // should print 2
console.log( myEmperor.isAlive ); // should print true

public

Using constructor notation, a property declared as this.property = “someValue;” will be public.

all properties of an object are automatically public;they can be accessed outside the class

Think of these properties as the information a class is willing to share

Example of public properties
function Person(first,last,age) {
this.firstName = first; // public
this.lastName = last; // public
this.age = age; // public
}

var john = new Person(‘John’,’Smith’,30);
var myFirst = john.firstName;
var myLast = john.lastName;
var myAge = john.age;

private

Using constructor, a property declared with var property = “hiddenValue;” will be private.

Just as functions can have local variables which can only be accessed from within that function, objects can have private variables. Private variables are pieces of information you do not want to publicly share, and they can only be directly accessed from within the class.
Example of private properties
function Person(first,last,age) {
this.firstname = first;
this.lastname = last;
this.age = age;
var bankBalance = 7500; // private
}

// don’t forget *new*
var john = new Person(“John”, “Smith”, 30);

// try to print his bankBalance
console.log(john.bankBalance); // returns undefined

accessing private variables of a class/object
We can define a public method that returns the value of a private variable.
Example of accessing private variables of a class/object
function Person(first,last,age) {
this.firstname = first;
this.lastname = last;
this.age = age;
var bankBalance = 7500;

this.getBalance = function() {
// your code should return the bankBalance
return bankBalance;
};
}

var john = new Person(‘John’,’Smith’,30);
console.log(john.bankBalance);

// create a new variable myBalance that calls getBalance()
var myBalance = john.getBalance();
console.log(myBalance); // do not need “john”

private methods of a class/object
Methods can also be private within a class and inaccessible outside of the class.

change the variable

Example of private methods of a class/object

// public method
this.getBalance = function() {
// your code should return the bankBalance
return bankBalance;
};

// private method
var returnBalance = function() {
return bankBalance;
};
// public method
this.askTeller = function() {
return returnBalance;
};
}

Changing this.returnBalance from above (private variables) to var returnBalance makes this method private.

function Person(first,last,age) {
this.firstname = first;
this.lastname = last;
this.age = age;
var bankBalance = 7500;

var returnBalance = function() {
return bankBalance;
};

this.askTeller = function() {
return returnBalance;
};
}

var john = new Person(‘John’,’Smith’,30);
console.log(john.returnBalance);
var myBalanceMethod = john.askTeller();
// askTeller returns a method, so we need to call it to use it, // see line below
var myBalance = myBalanceMethod();
console.log(myBalance);

passing arguments to the function of an object class

// the code here is modified to accept a password and return the balance if it’s correct

function Person(first,last,age) {
this.firstname = first;
this.lastname = last;
this.age = age;
var bankBalance = 7500;

this.askTeller = function(pass) {
if (pass == 1234) return bankBalance;
else return “Wrong password.”;
};
}

var john = new Person(‘John’,’Smith’,30);
/* the variable myBalance should access askTeller()
with a password as an argument */
var myBalance = john.askTeller(1234);

access value of a property in an object
var languages = {
english: “Hello!”,
french: “Bonjour!”,
notALanguage: 4,
spanish: “Hola!”
};

// print hello in the 3 different languages
for(var property in languages) {
var str = languages[property];
if (typeof str === “string”) {
console.log(languages[property]);
}
}

Example with prototypes

With prototypes:
– we can define a method for a class
– and any instance of the class (i.e., object created using that class’s constructor) can use that method

function Dog (breed) {
this.breed = breed;
};

// add the sayHello method to the Dog class
// so all dogs now can say hello
Dog.prototype.sayHello = function() {
console.log(“Hello this is a ” + this.breed + ” dog”);
};

var yourDog = new Dog(“golden retriever”);
yourDog.sayHello();

var myDog = new Dog(“dachshund”);
myDog.sayHello();

change variables in object from public to private

EXAMPLE
Modify the StudentReport class so that no grades will be printed to the console in the for-in loop. However, getGPA should still function properly in the last line.

function StudentReport() {
this.grade1 = 4;
this.grade2 = 2;
this.grade3 = 1;
this.getGPA = function() {
return (this.grade1 + this.grade2 + this.grade3) / 3;
};
}

var myStudentReport = new StudentReport();

for(var x in myStudentReport) {
if(typeof myStudentReport[x] !== “function”) {
console.log(“Muahaha! ” + myStudentReport[x]);
}
}

console.log(“Your overall GPA is ” + myStudentReport.getGPA());

ANSWER

function StudentReport() {
var grade1 = 4;
var grade2 = 2;
var grade3 = 1;
this.getGPA = function() {
return (grade1 + grade2 + grade3) / 3;
};
}

var myStudentReport = new StudentReport();

for(var x in myStudentReport) {
if(typeof myStudentReport[x] !== “function”) {
console.log(“Muahaha! ” + myStudentReport[x]);
}
}

console.log(“Your overall GPA is ” + myStudentReport.getGPA());

using literal notation to include the method “add”
var cashRegister = {
total:0,
*add: function(itemCost){*
this.total += itemCost;
}
};

//call the add method for our items
cashRegister.add(0.98);
cashRegister.add(1.23);
cashRegister.add(4.99);
cashRegister.add(0.45);

//Show the total bill
console.log(‘Your bill is ‘+cashRegister.total);

*build a cash register*
Step 1

add “add” method

var cashRegister = {
total: 0,
//insert the add method here
add: function(itemCost) {
this.total += itemCost;
}, // WE NEED THIS COMMA

scan: function (item) {
switch (item) {
case “eggs”:
this.add(0.98);
break;

case “milk”:
this.add(1.23);
break;

case “magazine”:
this.add(4.99);
break;

case “chocolate”:
this.add(0.45);
break;
}
return true;
}
};

//Scan 2 eggs and 3 magazines
cashRegister.scan(“eggs”);
cashRegister.scan(“eggs”);
cashRegister.scan(“magazine”);
cashRegister.scan(“magazine”);
cashRegister.scan(“magazine”);

//Show the total bill
console.log(‘Your bill is ‘+cashRegister.total);

Step 2

Add quantity

var cashRegister = {
total:0,
add: function(itemCost){
this.total += itemCost;
},
scan: function(item, quantity) {
switch (item) {
case “eggs”: this.add(0.98 * quantity); break;
case “milk”: this.add(1.23 * quantity); break;
case “magazine”: this.add(4.99 * quantity); break;
case “chocolate”: this.add(0.45 * quantity); break;
}
}
};

// scan each item 4 times
cashRegister.scan(“eggs”, 4);
cashRegister.scan(“milk”, 4);
cashRegister.scan(“magazine”, 4);
cashRegister.scan(“chocolate”, 4);

//Show the total bill
console.log(‘Your bill is ‘+cashRegister.total);

Step 3

void the last item

var cashRegister = {
total:0,
//Dont forget to add your property
add: function(itemCost, lastTransactionAmount) {
this.total += itemCost;
this.lastTransactionAmount = itemCost;
},
scan: function(item,quantity) {
switch (item) {
case “eggs”: this.add(0.98 * quantity); break;
case “milk”: this.add(1.23 * quantity); break;
case “magazine”: this.add(4.99 * quantity); break;
case “chocolate”: this.add(0.45 * quantity); break;
}
return true;
},
//Add the voidLastTransaction Method here
voidLastTransaction: function(lastTransactionAmount) {
this.total -= this.lastTransactionAmount;
}

};

cashRegister.scan(‘eggs’,1);
cashRegister.scan(‘milk’,1);
cashRegister.scan(‘magazine’,1);
cashRegister.scan(‘chocolate’,4);

//Void the last transaction and then add 3 instead
cashRegister.voidLastTransaction(“lastTransactionAmount”);
cashRegister.scan(‘chocolate’,3);

//Show the total bill
console.log(‘Your bill is ‘+cashRegister.total);

Step 4

apply a staff discount

function StaffMember(name,discountPercent){
this.name = name;
this.discountPercent = discountPercent;
}

var sally = new StaffMember(“Sally”,5);
var bob = new StaffMember(“Bob”,10);

// Create yourself again as ‘me’ with a staff discount of 20%
var me = new StaffMember(“Jenni”, 20);

var cashRegister = {
total:0,
lastTransactionAmount: 0,
add: function(itemCost){
this.total += (itemCost || 0);
this.lastTransactionAmount = itemCost;
},
scan: function(item,quantity){
switch (item){
case “eggs”: this.add(0.98 * quantity); break;
case “milk”: this.add(1.23 * quantity); break;
case “magazine”: this.add(4.99 * quantity); break;
case “chocolate”: this.add(0.45 * quantity); break;
}
return true;
},
voidLastTransaction : function(){
this.total -= this.lastTransactionAmount;
this.lastTransactionAmount = 0;
},
// Create a new method applyStaffDiscount here
applyStaffDiscount: function(employee) { //need parameter
this.total -= (this.total * (employee.discountPercent/100));
}

};

cashRegister.scan(‘eggs’,1);
cashRegister.scan(‘milk’,1);
cashRegister.scan(‘magazine’,3);
// Apply your staff discount by passing the ‘me’ object
// to applyStaffDiscount
cashRegister.applyStaffDiscount(me);

// Show the total bill
console.log(‘Your bill is ‘+cashRegister.total.toFixed(2));