1) why does john.getBalance() (last line) not result in an error when the getBalance function was not declared as this.prototype.getBalance but as this.getBalance? I thought subclasses could only use the functions of superclasses if they were declared with "prototype".
As I said in my answer to your last question, there is only one set of properties. Javascript will look first on the object itself and if no property match is found there, it will look on the prototype. There is no separate set of properties that belong to subclass and separate set for superclass. There is one set of properties directly on the object and there is a defined lookup order (for how to search the prototypes) if no matching property is found directly the object itself, but it is logically one overall set of properties on the object (and a method is just a property with a function for its value). There is not one set of properties that belong to the superclass and one set to the subclass. In Javascript you should not think of it that way (I know it feels like that in some other languages, but it isn't that way in javascript).
2) What is the difference between declaring the function this.getBalance vs Person.getBalance?
this.getBalance refers to a method on a specific object.
Person.getBalance refers to a property on the Person constructor which is not something you've declared.
If you mean the difference between declaring this.getBalance and Person.prototype.getBalance, then the main difference is where the function is found in the lookup order. Both will be found on any Person object or any object derived from a Person object. Technically it is more efficient for the runtime if you declare it on the prototype because there is only one shared instance of the function object rather than creating a new instance of the function object for each instance of Person, but operationally they are the same. Using the prototype is preferred unless there is a specific reason not to.
3) Is declaring the function inside vs outside the constructor just a convention or does it make a functional difference?
It is more efficient to declare methods on the prototype, but they can also be declared in the constructor and there is little operational difference except that methods declared in the constructor have access to local variables declared in the constructor which can be used as private instance variables. Using the prototype is preferred unless there is a specific reason not to.
4) If bankBalance is private, how do I know what functions are allowed to access it? Why is getBalance in the code allowed to access bankBalance?
Only functions declared within the constructor (where bankBalance is declared) can access it. This is just plain javascript scoping rules, but comes in handy if you want to implement a private instance variable like this.