Object-oriented languages have following features:
foo()
and foo(bar)
and foo(bar1, bar2)
... in a classThere are other less shortly explainable features, but lets sum up now for JavaScript.
I would say, three of seven.
"Of course, JS is object-oriented, isn't everything in JS an object?"
"Yes", I answered, "and its functional too, everywhere you see functions ..."
The following is a result of my studies about JS inheritance, but it is nothing I can recommend, and you won't find a working inheritance solution here. You could skip this and read about functional inheritance, which is what I would advice.
The only thing that is sure about JavaScript is that it is very flexible. So some kind of inheritance must be there, right?
If you search the web for JavaScript inheritance examples, you find things like this:
1 | var Animal = function(species) { |
Animal
and Cat
are called constructor functions, and thus have capitalized names.
(You should never call such a function without the new
operator, because such could cause unintended global variables.)
In Cat we have a super-object call which looks (and is) a little tedious:
Translated this reads as "take the overwritten function toString() from Cat's prototype object and execute it as if it was bound to 'this' Cat".Cat.prototype.toString.call(this);
The line
is the "inheritance installation", meaning this is what you are supposed to do when you want an object to inherit from another (as there are no classes, you need objects that you can inherit from).Cat.prototype = new Animal("FourLegs");
The line
is for a proper constructor function, so that calling a Cat's constructor would create aCat.prototype.constructor = Cat;
Cat
instance and not an Animal
instance. Here is some test code:
1 | var garfield = new Cat("Garfield"); |
This code outputs:
Garfield = Garfield <FourLegs (none)>
Catbert = Catbert <FourLegs (none)>
Garfield after meal = Garfield <FourLegs (mouse)>
Catbert after meal = Catbert <FourLegs (cheese)>
What is in (parentheses) is what the cat has in its belly.
We need to make sure that Catbert
has nothing in its belly that Garfield
has eaten ;-)
No problem until now, except that everything is public. Now I bring in what I would call a "private variable":
1 | var Animal = function(species) { |
My expectation is that every instance of Cat has its own private privFood
variable. The public food
variable is for checking whether that assumption holds.
Running the same test lines as above, guess what's the result!
Garfield = Garfield <FourLegs (none / empty)>
Catbert = Catbert <FourLegs (none / empty)>
Garfield after meal = Garfield <FourLegs (mouse / cheese)>
Catbert after meal = Catbert <FourLegs (cheese / cheese)>
How can Garfield have "cheese" as its privFood
variable?
When you consider that Garfield first eats a mouse, than Catbert eats "cheese", and Garfield then has "cheese" in its belly - this can not be a very private belly :-)
Isn't this a nice gotcha?
The privFood
variable comes from the Animal
instance in the prototype of Cat
that Garfield and Catbert have in common! Not even always putting a new Animal
instance to the Cat
prototype when creating a new Cat helps.
This is the moment when JS experts start to talk about the "prototype chain", and complex diagrams are drawn.
At some point the technical issues become so overwhelming that you forget about the nice web-page you wanted to implement; that point is trespassed here and now.
prototype
, encapsulation (private variables) is becoming an expert work. Thus mostly everything will be public and mutable, at any time and from anywhere.ɔ⃝ Fritz Ritzberger, 2014-10-16