Javascript class creation - javascript

I currently use this style to create a js class like structure:
var JSClass = (function(){
console.log('JSClass Init');
//-- Set up private var and fnc here
var opt = {
width: 0,
height: 60
}
function _PrivateSum(g){
return (g * opt.width);
}
//-- Set up public access here
function JSClass(){ //the class constructor
//-- class attributes
}
//-- class methods
JSClass.prototype = {
getWidth : function(){
return _PrivateSum(opt.width);
},
setWidth : function(w){
console.log('JSClass setWidth: ' + w);
opt.width = w;
},
getHeight : function(){
console.log('JSClass getHeight');
return opt.height;
},
setHeight : function(h){
opt.height = h;
}
};
return JSClass;
}());
init by calling the following in another page:
var jc = new JSClass();
This is all good etc but if I then need to create a class that I would like to use several times on the same page:
var jc = new JSClass();
var jc2 = new JSClass();
At present if I change anything within the first "jc" then it also controls what is in the second "jc2".
So my question is how would I go about creating a fresh instance of my JSClass() class so that i can manipulate each one individually with out effecting the current one, similar to php classes etc
I believe I would need to somehow create a clone of the original but am not sure, or if there is a better way than above please feel free to inform me
much appreciated

I like to use a construction like this:
note: no new-statement.
//definition
var myClass = function() {
var abc = 1; //private properties
function f1() {...}; //private methods
return {
bar: function() {} //public function *with* access to private members and functions
};
};
//usage:
var myInstance1 = myClass();
var myInstance2 = myClass();

All Your class instances will use the same opt object, so changing it in one instance will change it for all other instances, too.
You'll have to move opt into the constructor function. The prototype functions than loose access to opt, of course.
If you want to use the functional approach for classes with private members, you have to give up the beauty of the prototype, and inheritance will be complicated. But you'll get real private members.
Crockford's "The Good Parts" is a reading I would recommend for these things.

Your variables ("opt") are STATIC (class variables - i.e. shared across all instances of the class) not instance variables. Instance variables are properties on the "this" object, which you create in the constructor and/or the two set(ter) functions you have. In setWidth,setHeight replace opt.width (or height) with this.width (or height) and remove the static var "opt".
Also, move _PrivateSum into the prototype object or you willo have trouble accessing the new instance variable just introduced - unless you call it using _PrivateSum.call(this, this.width), because when calling it as you do now "this" will be wrong, but if it's an instance method and you call it with this._PrivateSum(...) inside it "this" will point to the correct object.

Related

JavaScript - Private members explanation?

Im reading this article from Crockford:
http://www.crockford.com/javascript/private.html
And in the section where he talks about Private, he says:
Private members are made by the constructor. Ordinary vars and parameters of the constructor becomes the private members.
Now if I do this in my script:
"use strict"
function car(brand) {
this.brand = brand;
var year = 2012;
var color = "Red";
}
var bmw = new car("BMW");
console.log(bmw.brand); // BMW -> VISIBLE ?!?
I can easily access property that was passed through constructor!
Can someone explain this better, shouldn't these variables passed through constructor be private?
Thanks!
I think you've mis-interpreted that bit of information. It doesnt say that private methods are those that are "passed through" the constructor, it says its those that are "made by" the constructor.
To be clear, look at this:
function car(brand) {
var year = 2012;
var color = "Red";
}
That has 3 private variables. brand,year and color. By adding this line
this.brand = brand
You are creating a public property and assigning it the value from your private variable. That you've named the public property and the private variable the same thing is neither here nor there, if it makes it clearer think of it as
this.publicBrand = brand
It's not that you can access values passed into the constructor. What you've done is set this.brand equal to the value passed in the constructor. Therefore, the publicly available brand now has the same value that was passed in. The local brand inside the constructor != this.brand until you set it.
Everything you assign to the context (this inside function) is public available. Be aware that the context is the window object if you call the function without new
"use strict"
function car(brand) {
this.brand = brand; //Public (can be accessed from outside because it is attached to the context/this)
var year = 2012; //Private (inside function only)
var color = "Red"; //Private (inside function only)
}
var bmw = new car("BMW");
console.log(bmw.brand); // BMW -> VISIBLE -> this.brand = brans
Solution: Using closures to create a inaccessable "private" scope.
"use strict";
(function (parent) {
(function (parent) {
var instances = {};
parent.getPrivateInstance = function (c) {
return instances[c];
};
parent.setPrivateInstance = function (c, value) {
instances[c] = value;
};
} (this));
parent.Class = function (name) {
setPrivateInstance(this, {
name: name
});
};
parent.Class.prototype.logName = function () {
console.log(getPrivateInstance(this).name);
};
})(window);
var c = new Class("test");
c.logName(); // "test"
console.log(c.name); // undefined
Caution: Memory leak
This will create a situation wherein the garbage collector will no longer clear the memory associated with the instances of Class because it they will always be referenced, which results in a memory leak.
To combat this we'll have to manually remove the reference made to the instances of Class. This can be done by adding one piece of code after the parent.setPrivateInstance section and one piece of code after the parent.Class.prototype.logName section. Those pieces of code would look like this:
parent.deleteFromMemory = function (c) {
delete instances[c];
};
parent.Class.prototype.deleteFromMemory = function () {
deleteFromMemory(c);
};
Usage
c = c.deleteFromMemory();
For a example of all the pieces working together: https://jsfiddle.net/gjtc7ea3/
Disclaimer
As this solution causes a memory leak I would personally advice against using it unless you know what you are doing, as it is very easy to make mistakes here.

Flaws with the following implementation of private state of instance objects

I have read that private state of instance objects is generally not advised, and I would appreciate the help in pointing out the flaws/shortcomings of the following implementation.
Any advise/critique is greatly appreciated.
var namespace = {};
namespace.parent = {
parent_method1 : function () {},
parent_method2 : function () {}
};
namespace.child = function (properties) {
var private="secret";
this.prototype = {
create : function () {
this.unique = 'base';
this.unique += this.properties;
return this.unique;
},
get_private: function () {
console.log(private);
},
set_private: function (val) {
private = val;
}
};
var proto = Object.create(namespace.parent);
var instance = Object.create(proto);
for (var property in this.prototype) {
if (this.prototype.hasOwnProperty(property)) {
proto[property] = this.prototype[property];
}
}
instance.properties = properties;
return instance;
};
var a = namespace.child("a");
console.log(a.create());
a.get_private();
a.set_private("new_a_secret");
a.get_private();
var b = namespace.child("b");
console.log(b.create());
b.get_private();
a.get_private();
I would appreciate the help in pointing out the flaws/shortcomings of the following implementation.
I don't see anything wrong with your implementation of the var private, provided that it does what you expect it to do.
However, the big flaw of the code is: I don't understand it. What is your implementation supposed to do? It does not follow any of the standard patterns. This might be a shortcoming of the pseudo-methods and clear up when implementing a real world model; however as it stands it's quite confusing. Some documentation comments would help as well.
Specifically:
What does namespace.child do? It looks like a factory function, but I'm not sure what "childs" it does produce.
Also, for some reason it does set the namespace.prototype property to a new object on every invocation, which is then mixed into the instance object proto object. However, it leaves the internals (get_private, set_private) of the last created instance in global scope.
Are a and b supposed to be classes? Why do they have .create() methods, that initialise the class (instance?) - and should rather be called .init() if at all? Why do they return the .unique property value?
Why doesn't the child method initialize those factored objects right away?
What is that .properties field that holds a string value?
Why are you using two-level inheritance for those instance objects? Object.create(namespace.parent) is understandable, it inherits from a static object that is shared. But why is then Object.create(proto) used, copying some properties (create, get_private, set_private) on the proto and some properties (properties, unique) on the instance? Why distinguish between them?

Javascript TypeError: ... is not a Constructor - How can I make Constructors from Constructors?

I am trying to do object inheritance in Javascript - is the following possible to do in javascript?
Grandparent Object:
var shape=function(paramOpts){
this.opts={x:0,y:0,h:10,w:10};
$.extend(true,this.opts,paramOpts);
this.sides=0;
this.fill='#fff';
this.outline='#000';
// some methods
};
Parent Object
var square=new shape();
square.sides=4;
Child Object
var redbox=new square();
redbox.fill='#f00';
Running this I get the error TypeError: square is not a Constructor.
How can I make square a Constructor?
When you create square you don't get Function returned as your prototype, you get shape.
There are several ways you can inherit like this, personally; I like to use Object.create() i.e
function shape(paramOpts){
this.opts={x:0,y:0,h:10,w:10};
$.extend(true,this.opts,paramOpts);
this.sides=0;
this.fill='#fff';
this.outline='#000';
// some methods
};
var square = Object.create(shape);
square.sides = 4;
var redbox = Object.create(square);
redbox.fill = '#f00';
Support for Object.create goes as far back as IE9 but no farther, there are plenty of shims that will do this for you though.
If you don't want to use a shim you can do it the classical way, your shape definition's methods would be defined on the prototype chain for shape i.e:
shape.prototype.setFill = function shape_fill(colour) {
this.fill = colour;
return this;
};
And your following definitions of square and redsquare would simply "leech" the prototype from shape like below:
function square(){}
square.prototype = shape.prototype;
function redbox() {}
redbox.prototype = square.prototype;
I hope this helps and I've been clear :)
If I've not been clear, there's loads and loads of information on the various Object. functions on MDN
edit
Continuation from my last comment below, you can add a super method to your prototype to fire the construct like below:
redbox.prototype.super = square.prototype.super = function super() {
return shape.call(this);
};
With that you should be able to call square.super() to run the shape construct and you can do the same for redbox to do the same.
You can also include the shape.call(this); code inside your square and redbox function definitions to do it, probably neater but it's your choice in honesty, personal taste lends my favour to prototype.
square is not a function
You cannot instantiate from variable , However , you can instantiate
from function .
Another thing , shape is not a GrandParentObject , It is a constructor in you context(=Class in OOP terminology) .
Use this function :
function inherits(base, extension)
{
for ( var property in base )
{
extension[property] = base[property];
}
}
Shape Class:
var shape=function(paramOpts){
this.opts={x:0,y:0,h:10,w:10};
$.extend(true,this.opts,paramOpts);
this.sides=0;
this.fill='#fff';
this.outline='#000';
// some methods'
return this ;
};
Grandparent Object :
var shape1=new shape();
Parent Object
var square=new shape();
inherits(shape1,square)
square.sides=4;
Child Object
var redbox=new shape();
inherits(square,redbox)
redbox.fill='#f00';
UPDATE:
I note your comment in Shape Class (//some methods) . However , if you talk about OO, Adding Methods to Your shape Class , it will be as following (Using Prototype) :
shape.prototype.Perimeter=function(){
return this.opts.w * this.opts.h ;
}
Then you can apply it in your object shape1
shape1.Perimeter(); // 10*10=100
Here is a simple example of inheritance in JavaScript:
// Parent class
function Shape (sides) {
this.sides = sides;
this.fill='#fff';
}
// Child class
function Square (fill) {
// run the Parent class' constructor
Shape.call(this, 4);
this.fill = fill;
}
// Instantiate Child class
var redbox = new Square('#f00');

How to convert javascript object variable into a class

How do I define a class I can instatiate later?
I wrote myself a rotator class using jquery which looks like:
var Rotator =
{
Loop: null,
init: function(identifierName)
{
........
}
}
If i want to have one rotator on my page it's good. I just call Rotator.init() and it's ready.
However when I want to have 3 rotators i got to define 3 times the whole class code changing its name.
Way easier it would be if I could just do
Instance1 = new rotator;
Instance2 = new rotator;
Instance3 = new rotator;
The following is what your object literal might look like as a re-usable Named Function that can be instantiated multiple times:
var Rotator = function(name) {
this.Name = name;
this.Loop = null;
this.init = function(identifierName)
{
this.Name = identifierName;
};
};
// usage:
var foorotator = new Rotator('foo');
var barrotator = new Rotator('bar');
alert(foorotator.Name);
alert(barrotator.Name);
http://jsfiddle.net/JzWCL/
After Edit:
http://jsfiddle.net/mPzsq/
Xander's solution looks like an acceptable form for a class-like object used only once. If you plan to subclass or multiply instantiate it, however, you should apply methods to the prototype rather than defining them within the main class (constructor) function. For example:
var Rotator = function(name) {
//run your initialization logic inside this constructor function
this.Name = name;
this.Loop = null;
}
Rotator.prototype.someMethod = function() {
//method code
}
var rotator1 = new Rotator('foo');
var rotator2 = new Rotator('bar');
The reason to use this structure is to prevent the methods from being reconstructed every time the class is instantiated. By applying the methods to the prototype, they will be shared between all instances of the class.
I've found this to be a helpful reference for some basics of JavaScript class definition:
3 Ways to Define a JavaScript Class

Better way to access private members in Javascript

After reading a bit on Javascript's prototypical inheritance model, I change my style of constructing a class from
var Some_Class = function() {
this.public_method = function() {
};
(function() {
// constructor
}).call(this)
}
to
var Some_Class = function() {
(function() {
// constructor
}).call(this)
}
Some_Class.prototype.public_method = function() {
};
Although I understand that this is a good practice, but I am not allowed to access private methods from the public method anymore
var Some_Class = function() {
var private_member = 'whatever';
(function() {
// constructor
}).call(this)
}
Some_Class.prototype.public_method = function() {
return private_member; // not possible
};
After reading through an article here (Closure-created constructor), then I came out with this
var Some_Class = function() {
var private_member = 'whatever',
private_method = function(_some_value) {
// private method implementation
};
if(!arguments.callee.prototype.public_method) {
arguments.callee.prototype.public_method = function() {
private_method.call(this, private_method);
};
}
(function() {
// constructor
}).call(this)
}
However, what are the drawbacks of doing this?! or is there a better way of doing this if I want to access private member in the public method?
My answer is a non-answer: there's no built-in private access in JavaScript but that's okay because YAGNI. Here's how I make private members in my code:
function Some_Class() {
this._private_member = 'whatever';
}
Some_Class.prototype._private_method = function() {
};
That's good enough. It's not really worth it to jump through hoops when the only real purpose of private is to protect yourself from... yourself.
(I say this having spent many hours myself playing around with every permutation of closures and prototyping, just as you are, and finally saying "screw it, it's not worth it".)
The use of function scope variables and closures to simulate private variables/functions is a well established idiom in the javascript community. If the variable is truly intended to be private, I see no drawback to this approach (although some claim that performant code on certain browsers/hosts has to pay attention to how many closures get created).
In your example, the private_method (and its environment) is shared across all objects - since your public_method closure is created only the first time the object is constructed (and bound to the constructor's prototype property that sets the created object's internal prototype chain) - so the private_method that is used is only the one that was created the first time.
Here is some sample code that will help illustrate what is going on:
var global = 1;
var Some_Class = function() {
var private_method = 'whatever';
var now = ++global;
print("outer now: " + now );
private_method = function(_some_value) {
// private method implementation
print("inner now: " + now);
};
if(!arguments.callee.prototype.public_method) {
arguments.callee.prototype.public_method = function() {
private_method.call(this, private_method);
};
}
(function() {
// constructor
}).call(this)
}
new Some_Class().public_method(); // outer now: 2, inner now: 2
new Some_Class().public_method(); // outer now: 3, inner now: 2
new Some_Class().public_method(); // outer now: 4, inner now: 2
Are you sure that is what you want?
If your private_method does not need to refer to the enclosing object's state, then I see little benefit in doing things the way you are doing.
What I usually do (if i have to use 'new' to create my object) is the following:
function MyClass() {
var private_var = 1;
function private_func()
{
}
this.public_func = function()
{
// do something
private_func();
}
this.public_var = 10;
}
var myObj = new MyClass();
The downside to this approach is that each time you construct the object via 'new' you re-create all the closures. But unless my profiler tells me that this design choice needs to be optimized, i prefer its simplicity and clarity.
Also I don't see the benefit in your code of doing the following either:
(function() { }).call(this); // call the constructor
Why are you creating a separate scope in your constructor?
If you have not done so already have a look at this JavaScript Module Pattern, which allows you to access private methods and variables from within the public functions, etc.
Echoing John Kugelman: It's impossible to create private members in javascript. Live with it. Even if you create a enclosure like this:
function SomeClass() {
var _private = 0;
this.public_acessor = function() {return _private};
}
Any user can still write:
SomeClass._not_private_anymore = 1;
SomeClass.public_acessor = function () {return this._not_private_anymore};
In the end, you can't trust any public member to be the same you declared. If someone is up to break your code, he will! Another user won't break your code only because it's useful.
Works with prototype, not just singleton. Problem is, when it's time to subclass, my subclass has no access to the privates

Categories

Resources