Javascript inheritance scoping question - javascript

I'm trying to get my head around JS inheritance using the "Pseudo-classical inheritance" style. I've done many Google searches and have read the classic articles. I'm familiar with Java's class structure and am trying to understand JS's prototypal style. I'm looking for vanilla JS since I want to understand the basics first.
I have a simple parent/child test class setup and need some help with the scoping rules.
1.) When do I define methods in the class vs outside of the class?
2.) How do I access private variables and private functions when I create methods using the prototype style?
function superClass(name){
this.name = name;
var privateValue = "I'm Private";
this.outputPrivate2 = function(){
alert(privateValue); //works fine
}
}
superClass.prototype.outputPrivate = function(){
alert(this.privateValue); //outputs undefined..
alert(superClass.prototype.privateValue) //also undefined
}
3.) How Can child objects call private functions or access private variables of the parent?
4.) When should the child object manually call the parent constructor?
subClass2.prototype = new superClass(); // Define sub-class
subClass2.prototype.constructor = subClass2;
function subClass2(name) {
this.name = name;
this.Bye = function() {
return "Bye from subClass - " + this.name;
}
this.testm = function(){
superClass.prototype.SomeParentMethod.call(this, "arg1", "arg2");
}
}
var parent = new superClass("parent");
var child = new subClass("child1");
parent.outputPrivate(); //undefined
parent.outputPrivate2(); //I'm private
child.outputPrivate(); //undefined
child.outputPrivate2(); //I'm private
I had three objects where 80% of the code was duplicated so I created a parent object and three child objects. The child objects have methods that use and manipulate private data from the parent. The only way I've gotten this to work is make all variables public which I don't like. Again, my familiarity is with Java so I might be trying too hard to make JS work like Java.

You're addressing some interesting points of object oriented JavaScript here.
1) When you define a method in the class, a new function will be created every time you call the constructor. This may lead to performance issues if you use a lot of objects. When you attach a method to the prototype object, the function is created only once.
2) But the advantage of defining functions inside the constructor is that you can use "private" methods/properties. In Javascript, there isn't really something like a private variable. Instead, you are creating a closure which contains some variables.
If you need to use these variables anyway outside the constructor, you need to make them public.
3) Same problem.
4) Although your question is not totally clear, I would do something like this:
function parent(){
this.a = 1;
}
function child(){
parent.call(this);
this.b = 2;
}
obj = new child();
// now obj.a == 1, obj.b == 2

Related

Function as a class - create getters and setters for private properties

The way I figured, when creating a new function (that represents a class), it is considered a good practice to define additional functions with the help of the prototype. If functions are declared through this within an existing function, they get created for each instance, which we don't necessarily want.
So, my question is - if I want to have a property that is completely private and can be access only through getters and setters, is it even possible to achieve this by using the prototype?
Here's an example:
function Item() {
var title = '';
this.setTitle = function(_title) {
title = _title;
};
this.getTitle = function() {
return title;
};
}
var car = new Item();
car.setTitle('car');
console.log(car.getTitle()); //car
console.log(car.title); // undefined
/*
Alternative
*/
function _Item() {
this.title = '';
}
_Item.prototype.setTitle = function(_title){
this.title = _title;
};
_Item.prototype.getTitle = function() {
return this.title;
};
var _car = new _Item();
_car.setTitle('car 2');
console.log(_car.getTitle()); // car
console.log(_car.title); // car
as can be seen from the example above, in the case of Item, I declared getters and setters within a function - not a good practice. But in this way, I managed to keep the title property private. However, in case of _Item, I'm using the prototype approach, which is preferred, but my title property is not private at all.
So, what's the best approach at creating private properties of "classes" in JavaScript?
No, if you want a private property, which by definition is a variable local to the constructor, then obviously methods which access it must also be defined within the constructor.
Many people worry about the efficiency implications of defining a method once on a prototype, versus defining it once on every instance. This might have been a valid concern ten years ago, or today in applications that are creating thousands or millions of objects. Otherwise, realistically it's not something you need to worry about.

Javascript Modular Prototype Pattern

The problem with functional inheritance is that if you want to create many instances then it will be slow because the functions have to be declared every time.
The problem with prototypal inheritance is that there is no way to truly have private variables.
Is it possible to mix these two together and get the best of both worlds? Here is my attempt using both prototypes and the singleton pattern combined:
var Animal = (function () {
var secret = "My Secret";
var _Animal = function (type) {
this.type = type;
}
_Animal.prototype = {
some_property: 123,
getSecret: function () {
return secret;
}
};
return _Animal;
}());
var cat = new Animal("cat");
cat.some_property; // 123
cat.type; // "cat"
cat.getSecret(); // "My Secret"
Is there any drawbacks of using this pattern? Security? Efficiency? Is there a similar pattern out there that already exists?
Your pattern is totally fine.
There are a few things that you'd want to keep in mind, here.
Primarily, the functions and variables which are created in the outermost closure will behave like private static methods/members in other languages (except in how they're actually called, syntactically).
If you use the prototype paradigm, creating private-static methods/members is impossible, of course.
You could further create public-static members/methods by appending them to your inner constructor, before returning it to the outer scope:
var Class = (function () {
var private_static = function () {},
public_static = function () {},
Class = function () {
var private_method = function () { private_static(); };
this.method = function () { private_method(); };
};
Class.static = public_static;
return Class;
}());
Class.static(); // calls `public_static`
var instance = new Class();
instance.method();
// calls instance's `private_method()`, which in turn calls the shared `private_static();`
Keep in mind that if you're intending to use "static" functions this way, that they have absolutely no access to the internal state of an instance, and as such, if you do use them, you'll need to pass them anything they require, and you'll have to collect the return statement (or modify object properties/array elements from inside).
Also, from inside of any instance, given the code above, public_static and Class.static(); are both totally valid ways of calling the public function, because it's not actually a static, but simply a function within a closure, which also happens to have been added as a property of another object which is also within the instance's scope-chain.
As an added bonus:
Even if malicious code DID start attacking your public static methods (Class.static) in hopes of hijacking your internals, any changes to the Class.static property would not affect the enclosed public_static function, so by calling the internal version, your instances would still be hack-safe as far as keeping people out of the private stuff...
If another module was depending on an instance, and that instance's public methods had been tampered with, and the other module just trusted everything it was given... ...well, shame on that module's creator -- but at least your stuff is secure.
Hooray for replicating the functionality of other languages, using little more than closure.
Is it possible to mix functional and prototypical inheritance together and get the best of both worlds?
Yes. And you should do it. Instead of initializing that as {}, you'd use Object.create to inherit from some proto object where all the non-priviliged methods are placed. However, inheriting from such a "class" won't be simple, and you soon end up with code that looks more like the pseudo-classical approach - even if using a factory.
My attempt using both prototypes and the singleton pattern combined. Is there a similar pattern out there that already exists?
OK, but that's something different from the above? Actually, this is known as the "Revealing Prototype Pattern", a combination of the Module Pattern and the Prototype Pattern.
Any drawbacks of using this pattern?
No, it's fine. Only for your example it is a bit unnecessary, and since your secret is kind of a static variable it doesn't make much sense to me accessing it from an instance method. Shorter:
function Animal(type) {
this.type = type;
}
Animal.prototype.some_property = 123;
Animal.getSecret = function() {
return "My Secret";
};

Private static in JavaScript and Inheritance

I understand how private static mechanism works in javascript; but that screws in
inheritance.
For example:
var Car = (function() {
var priv_static_count = 0;
return function() {
priv_static_count = priv_static_count + 1;
}
})();
var SedanCar = function () {};
SedanCar.prototype = new Car();
SedanCar.prototype.constructor = SedanCar;
Is there any way to avoid this pitfall ?
First of all, there's no such thing as "private static" in JavaScript. What you use here is a simple closure, which is created by a Immediately-Invoked Function Expression.
Your question is not quite clear, but I guess you want to count the Car instances that were created, and it doesn't work, because when you instantiate the subclass the counter won't increment (problem 1). Instead, the counter is incremented only once, when you define your subclass (problem 2).
Since JavaScript has a prototype based inheritance model, you have to create an object that can be used as prototype. But I suggest you to do it without calling the parent class' constructor (this will solve the second part of the problem). This is a very common pattern used everywhere in the JavaScript world (see Simple JavaScript Inheritance, Backbone, CoffeScript, etc.), and it is very simple to implement if you don't need to support very old browsers (IE6-8). It goes like this:
SedanCar.prototype = Object.create(Car.prototype)
Now the first part of the problem is quite simple to fix. Just call the parent constructor every time the child is instantiated. This is also a quite good pattern, and it is built into many other languages (Java, etc.). In JavaScript, you will have to do it manually, like this:
var SedanCar = function () {
// Parent class initialization
Car.call(this /*, and, other, arguments, to, the, parent, constructor */)
// Child class initialization
};
This will call the parent constructor with this bound to the newly created object. The parent constructor does the initialization, and then the child does it's share of the work. In your example, the parent will increment the counter as you would expect.

JavaScript: Inheritance by prototype, without using prototype to define/call methods

I've been making several libraries and extension libraries, and it's not practical for me to use prototype because in the real-world you actually have private variables that do not need to be accessed from an instantiated object.
var parent_class = function(num) {
var number = num;
this.method = function(anum) {
number += anum;
};
this.getNumber = function() {
var fnumber = number + 2;
return fnumber;
};
};
var child_class = function(num1, num2) {
var sum = num1 + num2;
parent_class.call(this, sum); // initialize parent class
this.method = function() {
sum -= 1;
base.method(sum); // what to do here
};
};
child_class.prototype = new parent_class(); // inherit from parent
child_class.prototype.constructor = child_class; // maintain new constructor
var c = new child_class(1, 4); // child_class.sum = 5, parent_class.number = 5
c.method(); // child_class.sum = 4, parent_class.number = 9
var num = c.getNumber(); // returns 11
Now, without declaring and relying on methods being prototyped, how can I get the what to do here line to work? I understand that I could call this.method(); inside child_class and store it as a variable, but I want overridable methods.
My previous topic was not very forthcoming, as everyone assumes I can just prototype everything or use private variables to get around the problem. There has to be a way to do this without prototyping.
I want to call .method(); from inside an instance of child_class without storing the previous .method(); as a private variable or using prototype methods that, for obvious reasons, cannot access private members.
Just use the prototype, you can mark "private" properties and methods with NULL character prefix or whatever to discourage people from using them, which is all you really need.
MyClass.prototype = {
"\0privateMethod": function(){}
};
If you're using chrome you will see this in console:
Object
privateMethod: function (){}
__proto__: Object
Yet one cannot do myClass.privateMethod(), this should be enough of a hint that this is a private property. To actually call it, you'd need to write myClass["\0privateMethod"]().
After going back to using prototype, your problem should automatically become easy to solve.
You're trying to make JavaScript into something it's not.
Stop doing that.
JavaScript does inheritance through the prototype. Get used to it.
ADDENDUM
Okay, let's clarify.
JavaScript doesn't implement OOP like C++, Java, C#, VB.NET, or any other object oriented language. You have the prototype. You can extend the prototype. If you want to "override a method", you need a reference to the version that previously existed.
Now, the caveat is going to be that anyone, at any time, can come along and replace anything, anywhere. So any assumptions about the stability of your object model are flimsy, at best.
Let the prototype do its job. Any framework you build around it to try to mimic inheritance, abstract base classes, superclasses, and what not, is going to have its own headaches and become a maintenance nightmare.

Javascript: Accessing public method of prototype does not work

I want to create a simple class in Javascript with only one public function as follows:
function A(myTitle) {
var title = "";
this.getTitle = function() {
return title;
};
title = myTitle;
};
var anInstance = new A("first");
console.log("anInstance.getTitle(): '"+anInstance.getTitle()+"'");
// expecting to return "first"
This does work as expected.
Now I want to add this class as a prototype to a new class, that includes a new title variable, so that the getTitle() method returns the value of the variable instead:
var myA = new Object();
myA.title ="second";
myA.prototype = anInstance;
console.log("myA.getTitle(): '"+myA.getTitle()+"'");
// expecting to return "second"
But instead of the expected "second", it results in the following error:
TypeError: 'undefined' is not a function (evaluating 'myA.getTitle()')
What is the problem with this function access?
Update:
The key point for my question is the following: In my application I will create several thousand instances of type "A" and several more of other comparable types. Thus memory efficiency and performance do matter. So I thought it would be great to create the according methods (several more will follow, getTitle is only one example) only once and the "data objects" reference these methods. Is this possible?
If all you want is instance variables (and that's all I see you using), what's wrong with idiomatic JavaScript:
function A(title) {
this.title = title;
};
A.prototype.getTitle = function() {
return this.title;
};
var anInstance = new A("first");
var myA = new A("second");
You can implement both Self-like prototypal OO and Smalltalk-like class-based OO on top of JavaScript, but this only makes sense in case of inheritance hierarchies, where the flat model of JS (which favors composition over inheritance - it's easy to add new methods to the prototype or apply() arbitrary constructor functions, but you'll have to jump through some hoops to make inheritance work properly) is not sufficient.
As to why your code can't work: your getTitle() method returns a lexical instead of an instance variable, which takes no part in property resolution via the prototype chain and thus can't be overwritten your way; also, .prototype is a property of constructor functions which is used to initialize the internal [[Prototype]] property of newly created instances - setting .prototype on general objects has no effect whatsoever on property resolution.
Firstly JavaScript is not a class based language.
This works just as well and am unsure what you are trying to achieve with your solution:
http://jsfiddle.net/jRtD2/

Categories

Resources