NERDY AMIGO

documenting my programming journey here

Objects

JAVASCRIPT OBJECTS

WHAT ARE THEY AND WHY ARE THEY IMPORTANT

An Object is a collection of properties, and a property is an association between a name(key) and a value. A property's value can be a function, in which case the property is know as a method. In addition to objects that are predefined in the browser, you can define your own objects.

An object in JavaScript can be understood by looking at objects in real life, thus abstraction is weird in the programming world but if we look at real life objects we can begin to understand JavaScript objects.

OBJECTS IN REAL LIFE

Let's think of objects in real life first, let's say a car, we know a car has properties right? Those properties also have values, for example the property tire our car has tires right? And it has 4 of them. It also has a color, and that color can be any of the hundreds that we know of. The car can also have a model as a property, let's say the model for our was is chevrolet. We could get very granular but for now this is fine. So now we have our object which is a car with 4 tires and the model is chevrolet. Now let's turn this into a JavaScript object.

// lets make our car object
let car = {}; 
// this is how an empty object is created in JS
// let's add our properties
car.model = 'chevrolet'
// we asign properties in our object by appending the object's name and a `.` with the name of the property we are adding to it, in this case the `model` property, we then use the assignment operator to assigned this property a value, in this case `chevrolet`. With this we have created a property `model` with the value `chevrolet` inside the `car object`.

// let's assign the rest of our properties, just like we did with `model`
car.tires = 4
car.color = 'black';

// to look at our car object we could console.log it and it should be printed back for us
console.log(car)
So we have objects, and we can create and object but how to we access these properties and edit them? or delete them?
Le'ts talk about how to access propeties in an object because there are a few
// we will use the same object we created in our previous code block
// let's access some of the properties previously declared in the earlier block

console.log(car.model) 
console.log(car["color"])

Now that we can access properties inside the object we created, why don't we change them? Let's say we change the color of our car, we would need to update it right? Let's to that

// Again we are using the car object we first created ^
// let's first access the `color` property to see what the current color is
console.log(car.color) // should return black, but we got a fresh new paint job, so let's change it
car.color = 'red'
// here we have changed the color of the car to red, now let's console it to confirm
console.log(car.color) // should return red
Let's access the properties and values inside this object

To do this we have a couple of methods that all JS objects can access, this internal methods are given to us by the language and do need to be declared, we just called them by using . + method name. There is also a loop that we can use.

  • for...in loops

    • This method traverses all enumerable props of an object and its prototype chain.
  • Object.keys(obj)

    • This method returns an array with all the known enumerable propertie's names('keys') of an object obj
  • Object.getOwnPropertyNames(obj)

    • This method returns an array containing all own propeties' names of an object obj
/* 
	Lets use the methods described
	First lets use the loop to get all the props from our car object
*/

for(item in car) {
  console.log(item)
}
/*
	We should get all the property name in the object (model, color, tires), 
	we can go a step farther and use this to get the value of these props
*/

for(item in car) {
	let x = car[item];
	console.log(x)
}
// We should get the value of each property ('chevrolet', 'red', 4)
/* 
	Now let's use the Object.keys(obj) method.
	As we can see here we use the Object which contains a bunch of methods we can use on....`objects`!
	here we are using the Object.keys() method which takes in an object and return an array of all its keys
*/

let keysFromObj = Object.keys(car) // The variable keysFromObj now has an array with all the keys from the object
// We can access the value of these keys using the property names that we have in the array
keysFromObj.forEach(key => {
	console.log(car[key])
})
/*
	Let's use Object.getOwnPropertyNames()
	This method will return all property names
	includind the ones that set enumerable to false
*/

Object.getOwnPropertyNames(car) // returns array of ALL properties' names

Creating Object

We have created an object by assinging an empty object to a varible, this creates the object we want in memory but this would take too long if we had more than one object to create, plus if we had more than one, it would be good to have a way to generate these on the fly using the same properties but different values, for example, what if you had more than one car? We would need to replicate a lot of code to create both of these with what we know now. So let's add a few ways we can create objects that will make this tasks of creating mulitple cars all with their own properies a lot more efficent. Let's first see how we have created our car object.

/*
	Let's create our car object
	1)	We begin by setting a variable name to an empty object,
	JS does all the work for us and initialized the object
	with no properties, so it is an empty object
	2) We assign propety names to values

	That is all, we can repeat Step #2 as many times as we want
	with different properties and build our object, but if we wanted
	to make another `car` object we would need to repeat all this code.
	There should be an easier way of doing this.
*/

let car = {};
car.model = 'Chevrolet'
car.year = '1992'
car.color = 'black'
Constructor Function

Let's solve the problem we had with creating multiple cars without repeating much code, and as always what do we as programmers do when we need to re-use code? We use functions, in this case we will creating a contructor function. Here are the steps to create a constructor function.

  • Define the object type by writing a constructor function. There is a strong convention to use a capital initial letter.
  • Create an instance of the object with the new keyword.
/* 
	Let's create an Object using a constructor function, 
	remeber a constructor function must have an identifier
	that starts with a Capital letter and we must use the 
	new keyword when calling the constructor function
*/

function Car(model, color, year) {
	this.model = model;
	this.color = color;
	this.year = year;
}

/*
	Notice the use of `this` here, if you do not know what 
	`this` mean in JS, take a moment to read this:
	https://github.com/getify/You-Dont-Know-JS/tree/master/this%20%26%20object%20prototypes
	Here since we will be creating multiple instances of this object we need to make sure our
	context is the right one so we make sure we save the params that are being passed down
	within the context of the object that has been created. This ensures the values given to the
	properties are correct for each instance.
*/

// Let's use our constructor function
let fordPickup = new Car('ford', 'brown', '1973');
let honda = new Car('honda', 'white', '2005');

/*
	We have created two cars using our constructor function,
	our cars each have their own properties which contain the
	information we passed to the constructor function.
*/
Object.create()

The Object.create() method can be really useful because it allows us to choose the prototype object for the object you want to create, without having to define a constructor function.

/* 
	Let's use the `Object.create()` method here.
	With this method we can choose the prototype object
	This means we do not need a constructor function to
	create this relationship, we can just declare it
	ourselves
*/

var Vehicle = {
	type: 'Car', // Default value for our object
	displayType: function() { // method which displays the type property's content
		console.log(this.type);
	}
}

// Let's create a vehicle
var car = Object.create(Vehicle); // Created a car with the default props
var truck = Object.create(Vehicle);
truck.type = 'Truck' // Changed the default props in this object
truck.displayType() // -> 'Truck'

CHALLENGE

From Interview Question

This is from a programing interview I had - I struggled putting it together but got it at the end. You pass the tests once your function can interpolate the template using the given function. Your params for the function are a template(which is a string in this case) and an object which contains key and value pairs, the object's content will be what we will be replacing inside the template, if the template has no variables inside the object we just return the string as is.

A template looks like this: let template = 'hello @{name}'

The @{} contains a variable which will be evaluated to it's value if it is found inside the object we got as a second parameter in our function. If the variable does not exist as an item inside the object we got as a parameter then we should return the template as is, without any interpolation.

We have a couple tests that we need to pass, all in mocha.

The first thing I thought of was to use a regex to target what was inside the interpolation bounds(@{}), and then I got a bit stuck, I focused too much on the values inside the object, when I should have been using the keys, getting all the keys from the oject can be done with an internal method called Object.keys(obj). This method gets the keys from the given object and returns an array with all the keys. Now that we have those keys we can loop over them and use each key to look for its instance in the template, the template is saved inside the interpolatedString variable. I used forEach for the loop which gives me access to each key, the regex is defined inside the forEach we create the regex by building it using the current key as what it targets. I had @{.*?} here before but that just matched everything instead of only matching what I was looking for inside the template. Once the regex is declared we can use it with the String method replace. We return the interpolatedString variable which contains the updated template.

Looking back, I was a bit nervous and that did affect my performace, I did however tried to talk more and walk the interview through my thought process. Overall it was a good experience and I'm glad I got it at the end.

let _ = require('underscore'),
    Mocha = require('mocha'),
    expect = require('chai').expect,
    mocha = getTesterInstance.call(this);

function interpolate(template, parameterDictionary) {
    // YOUR CODE GOES HERE
  let arr = Object.values(parameterDictionary)
  let keys = Object.keys(parameterDictionary)
  
  var interpolatedString = template
 keys.forEach(key => {
   let reg = new RegExp("@{" + key + "}", "g")
   interpolatedString = interpolatedString.replace(reg, parameterDictionary[key])
 })
  
  return interpolatedString
  
}

describe('Tests for string interpolation', function() {
  
    it('no template variables should return original string', function() {
        let template = "hello, world"
        let params = { name: 'Jake' }
        
        expect(interpolate(template, params)).to.equal("hello, world");
    });

    it('template variable without corresponding value should keep template variable', function() {
        let template = "hello, @{name}"
        let params = { language: "en_US" }
        
        expect(interpolate(template, params)).to.equal("hello, @{name}");
    });
  
    it('should interpolate the string properly', function() {
        let template = "hello, @{first_name} @{last_name}"
        let params = { first_name: "Jake", last_name: "Radakovich" }
                      
        expect(interpolate(template, params)).to.equal("hello, Jake Radakovich");
    });
  
    it('should replace multiple instances of template variables', function() {
        let template = "@{first_name} @{first_name} @{first_name}"
        let params = { first_name: "Jake", last_name: "Radakovich" }
                      
        expect(interpolate(template, params)).to.equal("Jake Jake Jake");
    });
});


mocha.run();


// you can ignore everything below this line
// #########################################

function getTesterInstance() {
    var mocha = new Mocha({ui: 'bdd'})

    // Bit of a hack, sorry! (blame coderpad)
    mocha.suite.emit('pre-require', this, 'solution', mocha);

    return mocha;
}
NextPrevious