nlivaic
11/1/2018 - 11:29 AM

Classes and inheritance

Classes and inheritance

'use strict';

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

var fluffy = new Cat('Fluffy', 'White');
var muffin = new Cat('Muffin', 'Brown');

Cat.prototype.age = 3;
console.log('=== Prototypes ===');
console.log(Cat.prototype);
console.log(fluffy.__proto__);
console.log(Cat.prototype === fluffy.__proto__);

console.log('=== Instance property ===');
console.log(fluffy.age);            // JS checks if the object has a property (object does not have a property in this case).
console.log(muffin.age);            // If there is no property on the object, JS checks its prototype.
console.log(Object.keys(fluffy));   // No age in object keys. 'age' is on the prototype.
console.log(fluffy.hasOwnProperty('age'));    // Returns false.

console.log('=== Instance property and prototype property diverge ===');
fluffy.age = 5;         // We actually add a new property to 'fluffy'. We are not changing the prototype's property.
console.log(fluffy.age);
console.log(fluffy.__proto__.age);  // Remains unchanged.
console.log(fluffy.hasOwnProperty('age'));    // Returns true.
'use strict';

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

var fluffy = new Cat('Fluffy', 'White');

console.log('=== Chains of inheritance ===');
console.log(fluffy.__proto__);                      // Cat
console.log(fluffy.__proto__.__proto__);            // Object
console.log(fluffy.__proto__.__proto__.__proto__);  // null
var cat = {
  name: 'Fluffy', color: 'White',
  sleep: function() {
    console.log('Zzzzz');
  }
};
cat.age = 3;
cat.speak = function() {
  console.log('Meeeeeow');
}

cat.sleep();
cat.speak();
function Cat(name, color) {
  this.name = name;
  this.color = color;
}
  
var cat = new Cat('Fluffy', 'White');
  
console.log(cat);
var cat = Object.create(Object.prototype, 
    {
        name: {
            value: 'Fluffy',
            enumerable: true,
            writable: true,
            configurable: true
        },
        color: {
            value: 'White',
            enumerable: true,
            writable: true,
            configurable: true
        }
    });

console.log(cat);
// ES6 Only.
class Vehicle {
  constructor() {
    this.type = 'car';
  }
  start() {
    return `Starting: ${this.type}`;
  }
}

class Car extends Vehicle {
  constructor(id) {
    super();
    this.id = id;
  }
  identify(prefix) {
    return `${prefix} Car id: ${this.id}`;
  }
  start() {
    return 'In Car.start() ' + super.start();
  }
}
let car = new Car(12);
console.log(car);
console.log(car.start());
console.log(car.identify('somePrefix'));
console.log(car.type);    // From base type.
var cat = {
    name: { first: 'Fluffy', last: 'LaBeouf' },
    color: 'White'
};

console.log(Object.getOwnPropertyDescriptor(cat, 'name'));
Object.defineProperty(cat, 'name', {writable: false});
console.log(Object.getOwnPropertyDescriptor(cat, 'name'));  // See how writeable changes.
cat.name.first = 'Scratchy';
// cat.name = { first: 'Scratchy', last: 'Cholo' }; // Will throw because writable false.
Object.freeze(cat.name);
// cat.name.first = 'Scratchy';    // Will throw because name property is frozen.
console.log(cat.name);
var cat = {
    name: { first: 'Fluffy', last: 'LaBeouf' },
    color: 'White'
};

// for..in
console.log(Object.getOwnPropertyDescriptor(cat, 'name'));
Object.defineProperty(cat, 'name', { enumerable: false });
console.log(Object.getOwnPropertyDescriptor(cat, 'name'));  // See how enumerable changes.

for (var propertyName in cat) {     // Cannot iterate over 'name'.
    display(propertyName + ': ' + cat[propertyName]);
}

console.log(Object.keys(cat));          // Key 'name' is not shown.
console.log(JSON.stringify(cat));       // Property 'name' is not serialized.
var cat = {
    name: { first: 'Fluffy', last: 'LaBeouf' },
    color: 'White'
};

console.log(Object.getOwnPropertyDescriptor(cat, 'name'));
Object.defineProperty(cat, 'name', { configurable: false });
console.log(Object.getOwnPropertyDescriptor(cat, 'name'));      // See how configurable changes.
Object.defineProperty(cat, 'name', { configurable: true });     // Throws error.
Object.defineProperty(cat, 'name', { enumerable: true });       // Throws error.
Object.defineProperty(cat, 'name', { writeable: true });        // Does not throw error.

delete cat.name;    // Throws error.

console.log(cat.name);
var cat = {
    name: { first: 'Fluffy', last: 'LaBeouf' },
    color: 'White'
};

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];
        }
    });

console.log(cat.fullName);
cat.fullName = 'Muffin Top';
console.log(cat.name.first);
console.log(cat.name.last);
var arr1 = ['green', 'blue', 'yellow'];
Object.defineProperty(Array.prototype, 'last' , {
    get: function() {
        return this[this.length - 1];
    }
});
console.log(arr1.last);
var arr2 = [101, 202, 303];
console.log(arr2.last);