Edit in JSFiddle

function assert(value, desc) {
    var res = $("#results");
    var li = document.createElement("li");
    li.className = value ? "pass" : "fail";
    li.appendChild(document.createTextNode(desc));
    res.append(li);
}

// functions have prototype property which initially is set to an empty object
// it doesnt serve much purpose until the function is used as a constructor
function Person() {};
Person.prototype.goToWork = function () {
    return true;
};

var person1 = Person();
assert(person1 === undefined, "person1 is undefined");

var person2 = new Person();
assert(person2 && person2.goToWork && person2.goToWork(), "person2 is a object with goToWork");

// each object in javascript has a implicit property named constructor that references the constructor that was used to create the object. prototype then is the property of constructor therefore each object has a way to find its prototype
assert(true, person2.constructor);
assert(true, person2.constructor.prototype.goToWork);
assert(person2.constructor.prototype.goToWork(), "accessing prototype from instance");
assert(person2.constructor === Person, "constructor can be accessed via the constructor property");
assert(person2.constructor.prototype.goToWork === person2.goToWork, "both references are the same");

// constructor property can be used same as constructor
var person3 = new person2.constructor();
assert(person3 instanceof Person, "person3 is instance of Person");


// property attached to prototype after obj instantiation is still available
Person.prototype.goToPlay = function () {
    return true;
};
assert(person2.goToPlay(), "property attached to prototype after object instantiation is still available ");

// property references are resolved in the object first
// prototype is consulted only if its not able to find it in property
function Actor() {
    this.hasActed = false;
    this.act = function () {
        return !this.hasActed;
    };
};
var actor1 = new Actor();
Actor.prototype.act = function () {
    return this.hasActed;
};
assert(actor1.act(), "if same method names exist on prototype and in instance, instance method has precedence");

// Inheritance using prototype chain can be achieved via doing something like Subclass.prototype = new Superclass()
function Vehicle() {
    this.canDrive = true;
};

function Car() {};
Car.prototype = new Vehicle();
var x5 = new Car();
assert(x5.canDrive, "Car is inheriting from Vehicle");
assert(x5 instanceof Car, "x5 is instance of Car");
assert(x5 instanceof Vehicle, "x5 is instance of Vehicle");
assert(x5 instanceof Object, "x5 is instance of Object");

// its advicable to avoid extending native types because they can cause undesirable results. Especially, extending object and number should be avoided
// hasOwnProperty can be used to figure out whether properties are actually defined on an object instance versus imported from a prototype
assert(!x5.hasOwnProperty('canDrive'), "canDrive is a property of prototype and not instance");

// Not calling constructors as constructors can give undesirable results
function SomeConstructor(a, b) {
    this.c = a + b;
};
// a private variable inside the function which is inside document.ready function
var c = 6;
// new is not used so this will get called as a function and not as a constructor
var notUsedAsConstructor = SomeConstructor(1, 2);
// hence this == window so window.c is 3
assert(window.c === 3, "window.c is 3");
// just c is the local c inside this anonymous function
assert(c === 6, "c is 6 though");
assert(notUsedAsConstructor === undefined, "Didnt even get initialized");
<div id="results" />
body {
    margin:10px;
}
.pass {
    color:green;
}
.fail {
    color:red;
    text-decoration:line-through;
}