Objects

Objects Review: How many ways can we build an object

'use strict';
//  use strict causes JS to throw errors when otherwise it would just 
//  silently fail
//  also it disallows the use of deprecated features 
// PLUNKER LINK
//  http://plnkr.co/edit/FOjJx2IJgsuLSMJdnH1k?p=preview

1) Create an 'Object literal' with var obj = {}


var cat = { 
  name: 'Ms Stinky', 
  color: 'white',
  raining: true,
  
  speak: function() {
       console.log("Meow")
       display('Meow')
  }
}

cat.age = 3

if( cat.raining ) { 
   cat.speak();    //  what will print here?
}

cat.raining = false
  
if (!cat.raining) {
      console.log(cat.age) // what will print here?
}
// create an object and set it to "dogs"
var dogs = {
  // creates the property "raining" and sets it to true
  raining: true,
  // creates the property "noise" and sets it to "Woof!"
  noise: "Woof!",
  // creates the method "makeNoise", which when called, prints dogs.noise if .raining is true
  makeNoise: function() {
  // the 'this' keyword refers to the object it's called from
  // i.e. this.raining refers to the raining property of 'this' particular object
    if (this.raining === true) {
      console.log(this.noise);
    }
  }
};

// creates an object with a similar layout to "dogs" and sets it to "cats"
var cats = {
  raining: false,
  noise: "Meow!",
  makeNoise: function() {
    if (this.raining === true) {
      console.log(this.noise);
    }
  }
};

// calls the "makeNoise" methods for both objects
dogs.makeNoise();
cats.raining = true;
cats.makeNoise();

// creates a function called "massHysteria" which takes in both objects and
// prints a message to the screen if ".raining" is true for both of them
var massHysteria = function(dogs, cats) {
  if (dogs.raining === true && cats.raining === true) {
    console.log("DOGS AND CATS LIVING TOGETHER! MASS HYSTERIA!");
  }
};

massHysteria(dogs, cats);

node one.js
output >

Woof!
Meow!
DOGS AND CATS LIVING TOGETHER! MASS HYSTERIA!   

Let's look at other ways to build objects

2) Constructor Functions (with new keyword)


//  the 'new' keyword  is followed by a function to initialize the object
//  new is using the constructor function 

 function Cat(name, color) {
   this.name = name
   this.color= color
   this.raining = true
 }
var fluffy = new Cat('Fluffy', 'White')
var muffin  = new Cat('Muffin', 'Brown')

//  The  'this' keyword refers to an object, that object is whatever object 
//  executing the current bit of code, by default it's the "global Object", 
//  in the browser it's window object

3) using Object.create , passing Object.prototype

//  it's a lot of work doing it this way, 

var cat = Object.create(Object.prototype,{
 name: {   // creating properties and and their values 
   value: 'Ms Strinky',
   enumerable: true,
   writable: true,
   configurable: true
 },
  color: {
    value: 'Blue',
     enumerable: true,
     writable: true,
     configurable: true
  },
  raining: {
    value: true,
     enumerable: true,
     writable: true,
     configurable: true
  }
  
})

// view Properties 
console.log(Object.keys(cat) )  
console.log(fluffy.hasOwnProperty('age'))

// if enumerable is set to true, and JSON.stringify(cat) will work too
console.log(Object.getOwnPropertyDescriptor(cat, 'name'))

for( var propertyName in cat ) {   // if enumerable is set to true
    console.log(propertyName + ' :  ' + cat[propertyName])   // see name & value  
}

Object.defineProperty(cat, 'name', { enumerable: false } ) 

// Properties 
/* 
Cat {
value: fluffy
writable: true
enumerable: true
configurable: true
} */

4) ES6 Class syntax sugar, but it's using prototypes (ES6/EcmaScript 2015)


class Cat {
   constructor(name, color) {
     this.name  = name 
     this.color = color 
     this.raining = true
   }
   
   speak() {  // adding methods to classes 
     console.log("Meeoww")
   }
}

var cat = new Cat("Wild", "White");
console.log(cat);
cat.speak();

 var cat = {
  name: { first: 'Ms Stinky', last: 'DePasquale' },
  color: 'White',
  'Eye Color': 'Green'
}
Object.defineProperty(cat, 'fullname', {
     get: function() {
       return this.name.first + ' ' + this.name.last 
     }, 
     set: function(value) {
       var nameParts = value.split(' ');
       this.name.first = nameParts[0];
       this.name.last  = nameParts[1];
     }
}) 

cat.fullname = 'Shark Tank';
console.log(cat.fullname)

for( var propertyName in cat) {
  console.log(propertyName + ': ' + cat[propertyName])
}

//////////  Prototypes and adding define property 
var arr = new Array('red', 'blue', 'green')
Object.defineProperty(Array.prototype, 'last', { get: function() {
   return this[this.length-1] 
}})
var last = arr.last; 
var arr2 = ['one', 'two','three','four'];
console.log(last);
console(arr.last);
console(arr2.last); 


class Animal {
  constructor(voice) {
    this.voice = voice || 'wowooow'
  }
  
  speak() {
    console.log(this.voice)
  }
}

class Dog extends Animal {
  constructor(name, color, bool) {
    super('Whoff whooof')
    this.name = name
    this.color = color
    this.raining = true
  }
}

var doggi = new Dog('Doggi', "Black")
console.log(doggi.constructor)
//  Members of class are not enumorable by default
//  Object.keys(doggi.__proto__.__proto__)  will be empty
//  doggi.__proto__.__proto__.hasOwnProperty('speak')  will be true

// Every Function in JS has a prototype (hence prototype functional language)
/********************************
 * A Function's Prototype: 
 * A function's prototype is the object instance 
 * that will become the prototype for all objects created using this 
 * function as a constructor   */


// Every Object in JS has a __proto__ property 
/**********************************
 * An object's prototype: 
 * An object's prototype is the 
 * object instance from which 
 * the object is inherited.          */