Define Private field Members and Inheritance in JAVASCRIPT module pattern - javascript

I can define private member fields in module pattern using the code below
var myClass = function(){
var private_field1,private_field_2;
var private_func1 = function(){
//.......
}
//.........
var myObj = {
global_field1:2,
global_field2:"something",
global_func: function(){//......}
}
return myObj;
};
var obj = myClass();
This method works just fine, but the problem with this problem is that whenever I create a new object the copy of all the functions is created and loaded in memory (not like java where all objects of same class share same function memory)
I tried to use other method below:
var myClass = (function(){
var private_field1,private_field_2;//private static fields
var private_func1 = function(){
//.......
}
//.........
var Constr = function(){
//do something
}
Constr.prototype = {
//................
global_func: function(){//......}
}
return Constr;
}());
var obj1 = new myClass();
var obj2 = new myClass();
But the problem with this method is that obviously obj1,obj2 share same copy of private fields(so effectively they are static). So is there a way to define private fields in module pattern while using same copy of functions for the objects?
And for inheritance for the first method mentioned above, i first need to create a object inside the child class and then return that object.
var ChildClass = function(){
var childobj = myClass();
//override or add functions to childobj
return childobj ;
}
But this is effectively just wrapping the object of baseClass in childClass, Is there some other way to implement the same(for 1st or 2nd method) so that it can act like true java inheritance with protected, private, etc methods?

No. Privateness in JavaScript can only be done by scoping (and exporting from them: closures).
Those functions that need to access the private variables (and functions), called privileged methods need to be defined inside the constructor. Those methods that don't (which only interact with public properties or other methods) should be defined on the prototype object, so you will get a mixed approach in the end. Potentially combined with the static values you just discovered.
Btw, not the function [code] itself is copied and memorized multiple times. Only different scope objects (lexical environments) need to be stored.
Inheritance is usually not done by creating parent objects and extending them, but by creating child instances and extending them like a parent. This is can be done by applying the parent's constructor on the newly created child:
function ChildClass() {
ParentClass.call(this, /* … arguments */);
// usual body, using "this"
}
Also, the prototype of the Child inherits directly from the Parent's prototype object. This can be done via Object.create (needs to be shimmed for legacy browsers):
ChildClass.prototype = Object.create(ParentClass.prototype, {
constructor: {value:ChildClass}
});

Related

What are advantages to adding methods to a class vs adding methods to a class's prototype?

When I write a javascript class, its usually like this:
var myClass = function(prop1, prop2) {
this.prop1 = prop1;
this.prop2 = prop2;
this.method1 = function() {//blah}
this.method2 = function() {//blahblah}
}
But most books/tutorials I've read describe writing classes like this:
var myClass = function(prop1, prop2) {
this.prop1 = prop1;
this.prop2 = prop2;
}
myClass.prototype.method1 = function() {//blah}
myClass.prototype.method2 = function() {//blahblah}
What is the difference between these two approaches? Is one better than the other?
The second approach, using the prototype, is much more efficient if you create a large number of objects, and especially if you have a large number of methods.
The first approach requires all of the method functions to be created every time you call new myClass(). When you use the prototype these functions only have to be created once.
There is one advantage to the first approach: you can use your constructor function as a closure, so its methods have access to local variables in the constructor.
As a side note, your constructor function name should begin with a capital letter to follow normal JavaScript conventions.
What you implemented are just functions. They can be used as constructors for creating objects. When a constructor is invoked, a new object is created and it has its Prototype set to the constructor's prototype property, which means that it shares properties with constructor's prototype. In the first case method1 and method2 are properties of each object created using myClass constructor. If those methods are the same amongs all objects created that way, it is a kind of memory wasting. If you put those methods into constructor's prototype, no new copies of them will be created when constructor is invoked, but created objects would still have access to them using prototype chain. So it's generally for saving memory.

How to make a class in JavaScript?

There are lots of ways of doing the same thing in JavaScript. I have however picked up some ways, and some ways I frankly don't understand. Could anyone please help me clarify some things? (I first learnt OOP in PHP.)
So a class can be made like this:
var object = new class(constructparams) {
var private_members; // Can be accessed from within the code inside this definition only.
this.public_members; // Can be accessed from everywhere.
var private_functions = function() {}
this.public_functions = function() {}
}
object.prototype.semi_public_members = function() {
// Will be public, but can only access public members and methods.
// E. g. private_members; is not available here.
}
Is this all correct so far?
Then someone likes the self-executing anonymous function approach to create a namespace. What is the point of that, when you have this way above that does the same thing, provides a namespace?
And lastly you have the object literal notation that I don't understand.
var object = { // Something strange in here }
What is going on in there? Is it JSON? How is it used, how can I use it. What are the benefits of using this way instead of using the method I described? Why would you prototype instead of making the class correctly the first time?
Explaining the behaviour of different things in a constructed object by example:
// Defined as a variable from an anonymous function
// so that there is scope closure over variables
// shared across all instances and the prototype.
// If this isn't important, you don't need to close
// scope around it, so define directly
var ConstructedObject = (function constructorCreator () {
// Define any variables/methods to be shared across
// all instances but not polluting the namespace
var sharedVariable = 'foo';
// Next the actual constructor
function ConstructedObject () {
// Variables here are normally used to help
// each instance and will be kept in memory as
// long as the instance exists
var instanceVariable = 'bar';
// instance-specific properties get defined
// using the "this" keyword, these are the
// properties expected to be changed across
// each different instance
this.instanceProperty = true;
this.instanceMethod = function () { return instanceVariable; };
this.changeInstanceVar = function () { instanceVariable = 'foo'; };
// you do have access to the shared
// variables here if you need them.
}
// After the constructor, you set up the
// prototype, if any. This is an object of shared
// properties and methods to be inherited by every
// instance made by the constructor, and it also
// inherits the prototype's prototype, too.
// Lets use a literal object for simplicity.
ConstructedObject.prototype = {
// Accessing the instance to which a method
// applies is done using the "this" keyword,
// similar to in the constructor
sharedMethod : function () { return [sharedVariable, this.instanceMethod(),this.instanceProperty]; },
changeSharedVar : function () { sharedVariable = 'bar'; }
// properties may also be defined
};
// Finally, the constructor is returned so it
// can be kept alive outside of the anonymous
// function used to create it
return ConstructedObject;
// and the anonymous function is called to execute
// what we've done so far
})();
After executing the above code, you have a constructor that creates objects with both instance-specific and shared variables. Now let's look at how they behave by creating two of instances and comparing them before and after some changes.
// First create the two instances
var myObjA = new ConstructedObject(),
myObjB = new ConstructedObject();
// Now compare them, the sharedMethod method we
// used in the prototype offers an easy way to
// do this
console.log( myObjA.sharedMethod(), myObjB.sharedMethod() );
// ["foo", "bar", true] ["foo", "bar", true]
// Next lets change the different variables in
// myObjB so we can see what happens, again the
// change* methods defined before let us do this
// easily
myObjB.changeInstanceVar();
myObjB.changeSharedVar();
// For completeness, lets also change the property
// on myObjB.
myObjB.instanceProperty = false;
// Now when we compare them again, we see that our
// changes to the myObjB instance have only changed
// the shared variables of myObjA
console.log( myObjA.sharedMethod(), myObjB.sharedMethod() );
// ["bar", "bar", true] ["bar", "foo", false]
Here are the two logged statements together for easier viewing
// myObjA myObjB
["foo", "bar", true] ["foo", "bar", true]
["bar", "bar", true] ["bar", "foo", false]
I think there are some concepts that seem to be missing but I'll try answering as much as I can.
So a class can be made like this...Is this all correct so far?
It's close but is not entirely correct. You don't need new to create a constructor function, you only need it when creating a new instance of the "class".
function Klass() { ... } // capitalized name as convention for constructors
var myKlass = new Klass(); //<-- Need "new" here
Public methods can be attached to the instance or to the prototype. When you attach it to the prototype the method will be shared across all instances, saving some memory.
Klass.prototype = {
publicSharedMethod: function() {
var self = this;
}
}
Then someone likes the self-executing anonymous function... What is
the point of that...
The module pattern (or self-execution function) approach is a bit different because you're typically not dealing with the prototype although you can. It's just a function that returns a literal object with properties and methods but I mainly use it for singletons when you don't need instances of that object:
var Singleton = (function() {
var private = 'foo';
var public = 'baz';
var publicMethod = function() { ... }
// Expose public methods and properties
return {
public: public
publicMethod: publicMethod
}
}());
And lastly you have the object literal notation that I don't
understand.
That's just a regular object in JavaScript, similar to what PHP calls "associative array". Literal objects syntax are the base for JSON, but JSON has more limitations in terms of formatting; JavaScript is more forgiving so you can have unquoted properties and methods for example.
Why would you prototype instead of making the class correctly the
first time?
The point here is to understand that JavaScript is not a traditional object oriented language, so there are no classes, and you shouldn't be thinking about classes. But prototypes are very powerful, I'd say even more powerful than classes. There are many examples online on how to replicate classes with prototypes but not the other way around.
var object = new function () {
//
}
var myObject = new object();
No, that is not correct. The constructor function should be separate from the creation of the object:
function myClass(constructparam1) {
this.public_member = constructparam1; // Can be accessed from everywhere.
}
The methods should be in the prototype for the constructor, not the instance:
myClass.prototype.semi_public_members = function() {
// Will be public
}
Call the constructor with the new keyword to create the instance:
var obj = new myClass(1337);
Local variables inside the constructor function can only be accessed inside that function. If you wan't local variables in your class, you need a function around it to create a closure, so that the methods in the prototype can access the variables:
var myClass = (function(){
var local_variable;
function constructor(constructparam1) {
this.public_member = constructparam1; // Can be accessed from everywhere.
}
constructor.prototype.semi_public_members = function() {
// Will be public
alert(local_variable); // can access private variables
}
return constructor;
})();
Object literals is just a simple but limited way to create objects in one go. They don't have a prototype, so if you want them to have methods, you have to assign them to properties:
var obj = {
public_member: 1337,
semi_public_members: function(){
alert(this.public_member);
}
};

What is the best way of defining a class in javascript [duplicate]

This question already has answers here:
How can I emulate "classes" in JavaScript? (with or without a third-party library) [closed]
(7 answers)
Closed 10 years ago.
I have searched for a way of defining a class in javascript like in java or php but I found none!
I want something like
class javascriptClass {
function someFunction(){}
}
You can use a prototype class, like so:
function MyClass() {
}
MyClass.prototype.method1 = function() {
// do stuff
};
MyClass.prototype.method2 = function(p) {
// do stuff
};
var myClass = new MyClass();
Now, after instantiating an object myClass from the prototype MyClass, you can access the methods of the object myClass:
myClass.method1();
The above method is great if you need to instantiate more than one object/instance of the class.
If you only expect to have one object, then another method you can use simply acts as a namespace to protect your functions from collisions with others:
var myObject = {
method1: function() {
// do stuff
},
method2: function(p) {
// do stuff
}
};
myObject.method1();
In JavaScript, you don't have classes as such. You define functions that are used to create objects with new, and you can give them methods by either creating them in the body of the constructor, or adding them through the object's prototype. For example:
function JavaScriptClass() {
// I am a JavaScript constructor! Any initialization can be done here.
}
// This is the prototype! You can put instance methods and variables (to an extent) here.
JavaScriptClass.prototype.someFunction = function() {
alert('someFunction was called!');
};
// Now, let's create an instance!
var obj = new JavaScriptClass();
obj.someFunction(); // someFunction was called!
And you can access the current object using this, in both the constructor and any methods bound to the object. Note that this can also be bound to just about anything in JavaScript. It's a different type of OOP.
Unlike class-based languages, JavaScript is functional languages or prototypal language, you can't use class keyword or the kind of signature you have posted in JavaScript. In JavaScript, normally you would do:
function Person(){
// public members
this.foo = 'foo';
this.walk = function(){ ......... }
// private members
var bar = 'bar';
var baz = function(){.........}
}
var person = new Person();

JavaScript: Object.myMethod vs Object.protoype.myMethod?

I have an issue when I want to add a method to Object class in JavaScript. I don't know the different between Object.myMethod and Object.prototype.myMethod.
Object.myMethod = function (){};
Object.prototype.myMethod = function (){};
Can anyone help me out
Object is the constructor function. Like all functions in JavaScript, it is an object, and you can attach properties to it. Those properties can be functions. So doing
Object.myMethod = function () { };
attaches myMethod to the Object constructor function, which means you can call it like so:
Object.myMethod();
Object.prototype is the prototype used as a base for all JavaScript objects. It is itself an object, and so again you can attach properties to it. The difference is, properties attached to the prototype get prototypally-inherited by all objects via their internal [[Prototype]] reference, so something like this is possible:
Object.prototype.myMethod = function () { };
var obj = {};
obj.myMethod();
var otherObj = { something: "else" };
otherObj.myMethod();
var objectViaConstructor = new Object();
objectViaConstructor.myMethod();
var instanceOfSomethingThatInheritsFromObject = new XMLHttpRequest();
instanceOfSomethingThatInheritsFromObject.myMethod();
Note that most of the above applies for arbitrary constructor functions, with the exception that you do not get a special object literal syntax, and Object is special in that everything (up to and including the example XMLHttpRequest) inherits from it. So:
function MyConstructor() { }
MyConstructor.staticMethod = function () { };
MyConstructor.prototype.method = function () { };
MyConstructor.staticMethod();
var myConstructed = new MyConstructor();
myConstructed.method();
Object.myMethod is a method on a single object, it's similar to a Static Method in languages with classical OOP.
Object.prototype.myMethod is a method that will exist on all instances of an object, similar to an Instance Method (sometimes just called a Method, vs a Static Method) in languages with classical OOP.
If you're creating instances of your Object (i.e. new MyClass()) then use a prototype method.

Private AND Static AND Inherited variables!? Or similar

I'm building a system, with similar details as this question: Can I have different copies of a static variable for each different type of inheriting class
Except it's in JavaScript!
I'm going to have a set of subclasses. Each subclass will have a lot of instances created of it during the life of the program. Each instance of a particular subclass will have different values, except for a file that is common to all. I don't want each instance to have a copy. I want it static (one copy for all). Each different subclass uses a different file though. I want each subclass to inherit the FACT that it HAS a file from a superclass.
EDIT: Quick Summary:
goal: create a class that is a constructor that
constructs the definition of a
subclass, allowing a variable:
- Appearing in every subclass
- Unique to a particular subclass
- Shared by all instances of a particular subclass (one copy for all)
Attempt at illustrating this in code:
var instance1ofSubclass1 = {
staticVar:"SAMEVAL_1", // For brevity I'm showing how staticVar is
// the same. It's notsupposed to be public.
uniqueVar:"adsfasdf"
};
var instance2ofSubclass1 = {
staticVar:"SAMEVAL_1",
uniqueVar:"zxbvczbxc"
};
var instance3ofSubclass1 = {
staticVar:"SAMEVAL_1",
uniqueVar:"qwrtytry"
};
var instance1ofSubclass2 = {
staticVar:"SAMEVAL_2", //<--notice the static var is different
// between subclasses
uniqueVar:"oipoiuu"
};
var instance2ofSubclass2 = {
staticVar:"SAMEVAL_2",
uniqueVar:"hljkhlj"
};
var instance3ofSubclass2 = {
staticVar:"SAMEVAL_2",
uniqueVar:"bnmbmbmnm"
};
My class definitions could go like this:
var subclass1 = (function () {
var staticVar = "SAMEVAL_1"
return function (unique) {
return {
uniqueVar:unique
};
};
}());
var subclass2 = (function () {
var staticVar = "SAMEVAL_2" //<-- different static variable
return function (unique) {
return {
uniqueVar:unique
};
};
}());
Now, I want to go a step further and make a superclass for these classes. That's where I'm stuck. I don't want to have a staticVar definition in every subclass. I want to get it from the superclass.
First of, the compiler will never be able to prevent you from forgetting something since there is no compiler. That's something we'll have to live without.
My suggestion for you would be to use prototyping for this. If the prototype of the superclass contains your variable, the same instance will be used for all the subclasses. And you wont have to repeat yourself in your subclass-files. Static and inherited, so to speak.
MySuperClass.prototype.myStaticVar = "giantFile";
The downside of this solution is that the variable won't really be private. On the other hand, do you really, really need it to be private?
The concept of privacy is a little funny anyhow. In C/C++ everything (private stuff too) can be accessed by pointer-magic. In C# you can use reflection to alter private variables. Nothing is ever really private. JavaScript is even funnier since the scripts in the browser can be altered by the end-user himself! In my opinion, hiding in plain sight is the way to go in this case. Name your variable appropriately (for example, add an underscore or two the beginning of it's name to signify "privacy").
if i'm reading this right, I had a similar issue that you did. Check this SO question that i posted a few weeks ago.
to take that a step further, my .add() method checks to see if the passed in namespace has a supr object attached to it, if not, then it appends the base object called supr to that namespace so that it can have easy access to the root.
I think I've figured it out.
Fiddle: http://jsfiddle.net/zXMaM/
The pattern I've created sends a class definition through another function (essentially the super class) that creates an additional closure for the necessary private static variables and at the same time augments the object created by the class passed in to access the private static variables.
It's hard to explain as this is new to me too, but hopefully between the code and my comments it is followable.
The "superclass" method:
var superClass = function (yourPrivateStaticVar, classDef) {
var privateStatic = yourPrivateStaticVar;
return function () { // return a new constructor (only invoked when a new
// instance is created!)
// run the constructor, grab the object it creates
var newObj = classDef();
// now, augment the object created (these vars/methods have no
// knowledge of the subclass!)
//add private vars/methods to the object
function getPrivStatic() {
return privateStatic;
}
var example_inherited_private_var;
//add public vars/methods to the object
newObj.getPrSt_directly = function () {
return privateStatic;
}
newObj.getPrSt_throughPrivateFunc = function () {
return getPrivStatic();
}
newObj.example_inherited_public_var = "something";
//return the augmented object (a new *instance* of the subclass)
return newObj;
};
};
Defining a "subclass":
//pass the definition of subclass1 through the superclass method and get it back
var subClass1 = superClass("yourChosenPrivateStaticValue", function () {
//private variables/methods go here
return { //this is the actual instance object
//public variables/methods go here
};
});
Again, the fiddle: http://jsfiddle.net/zXMaM/

Categories