Declaring properties before using them - best practice? - javascript

I always declare properties on objects if i know i will use them in my code at some point (To help other developers not be surprised when a new property gets added onto an object in debugging process and wonder where or why it has been populated):
var TestHelper = function(){
var Test = function(){
// Public:
this.a = null; // string
this.b = null; // number
}
// Public:
return {
/*Test*/ TestFunction: function(str, num){
var test = new Test();
test.a = s;
test.b = num;
return test;
}
}
}
I can find it frustrating when i come across code like this:
var TestHelper = function(){
var Test = {};
// Public:
return {
/*Test*/ TestFunction: function(str, num){
var test = new Test();
test.a = s;
test.b = num;
return test;
}
}
}
or even harder (losing the javascript type that's helpful for debugging)
var TestHelper = function(){
// Public:
return {
/*{}*/ TestFunction: function(str, num){
return {
a = s,
b = num
}
}
}
}
... because it makes it just that bit harder to understand fully what the original developer had in mind.
Ignoring my opinion,
What are the various thoughts on this and why?
Do big teams generally like to declare properties first to help other developers, or visa versa?
Am i asking the right question or is there another point i am missing?

Of course developers prefer things documented it's easier for them.
A good practice in Javascript is to avoid undefined value, so for this it's far better to initialize your objects with null value, or empty array or empty objects.
However you forget a thing with your last case -> this approach when possible is the best :
function Test(str, num){
this.a=str;
this.b=num;
return this;
}
Test.prototype.method = function(a){...}//adding method to the object Test
var test = new Test("toto", 5);
test.method(a);//executing method

Related

Javascript prototype inheritance private method

I've been investigating multiple leveles of inheritance with "private" variable in each "class" in JavaScript, but run into this peculiar singularity:
function Ammo() {
var a = 0;
this.get_ammo = function() {
return a;
};
this.add_to_ammo = function() {
a = a+1
return a;
};
this.clean_ammo = function() {
return a=0;
}
}
function Weapon() {
var a =0;
}
function Gun() {
var a = 0;
this.fire = function(){
console.log("Bang");
}
}
Weapon.prototype = new Ammo();
Weapon.prototype.constructor = Weapon();
Gun.prototype = new Weapon();
Gun.prototype.constructor = Gun();
var a = new Ammo();
var w = new Weapon();
var g = new Gun();
a.add_to_ammo()
a.add_to_ammo()
a.add_to_ammo()
console.log(w.get_ammo())
// At this point I get 0, as expected. But after
w.add_to_ammo()
w.add_to_ammo()
w.add_to_ammo()
console.log(g.get_ammo())
// But here I get 3!
Can somebody explain why I get 3 after
console.log(g.get_ammo())
I thought that objects a, w, g are independent, so are their fields.
Also I found out that if I change
var a = 0;
to
this.a = 0;
I get expected result. fields of the object are unbound to their parents fields.
var a is defined in Ammo, but var a in the other constructors does absolutely nothing. The a that's being modified when you call the method no matter which instance is always the same a that was captured in the closure in Ammo.
You can't have private variables like you want in JavaScript, and that's ok. The most common way to do it is to make the variable public, and prefix it with an underscore, to mark it as "internal":
function Ammo() {
this._ammo = 0;
}
Then add the methods to the prototype and use this._ammo to reference that variable:
Ammo.prototype.getAmmo = function() {
return this._ammo
}
Then you can inherit with Object.create:
Weapon.prototype = Object.create(Ammo.prototype);
And in the constructor "call super":
function Weapon() {
Ammo.call(this) // gets own "_ammo"
}
Also, you are not setting up the constructor function properly. You should assign a function, not call it:
Weapon.prototype.constructor = Weapon;
Gun.prototype.constructor = Gun;
I don't have enough rep points to comment on #elclanrs answer, so forgive me.
His answer is all correct, but the most pertinent piece of information is the last
Also, you are not setting up the constructor function properly. You should assign a function, not call it:
Weapon.prototype.constructor = Weapon;
Gun.prototype.constructor = Gun;
your variables that are declared inside the scope of the function closure ARE IN FACT PRIVATE! however, you never properly instantiated you subclass objects, so you had a frankenstein thing going on: one object, lots of body parts.
Other than that there is nothing inherently wrong with your code, it's just not the way people usually write "Classes" and I won't explain why in the context of this question.

Javascript access variables in prototype without instantiating

Is it bad practice to access variables in a javascript class without instantiating it?
For example:
var Test = function(){
this.tests.push("Something");
}
Test.prototype.tests = [];
var test = new Test();
console.log(Test.prototype.tests); //Is this okay to do? Obviously I can use test.test here, but this is a poor example of why I am wanting to do this; it merely shows my question.
I've run across an instance where I only have an id and I want to use the class to get the correct instance of itself for me such that: Test.prototype.getByID(id); but I wanted to make sure it is proper to do this.
You could take advantage of closures in JavaScript and do something like the following (jsfiddle). This has the advantage of making your "list of tests" private so it can't be messed with and you don't have to access the prototype which does feel a bit odd:
var Test = (function() {
var tests = {};
var Test = function(id){
tests[id] = this;
this.id = id;
}
Test.getByID = function(id) {
return tests[id];
}
return Test;
}());
var test1 = new Test(1);
var test2 = new Test(2);
var test2_2 = Test.getByID(2);
alert( test1 === test2_2 );//should be false
alert( test2 === test2_2 );//should be true

how to have Javascript Object creation pattern with Reusable methods and private properties?

Considering object creation patterns with private properties, one way to do is :
function MyStack (){
var list = [],
index = 0;
this.push = function(val){
return list[index++] = val;
};
this.pop = function(){// ...}
}
var stack1 = new MyStack(); stack1.push(5);
var stack2 = new MyStack(); stack2.push(11);
Problem with this: Every instance of Stack has it's own copy of methods 'push' and 'pop'.
Another way for implementing constructor method is:
function MyStack(){
this.list = [];
this.index = 0;
}
MyStack.prototype = {
insert: function(val){
return this.list[this.index++] = val;
},
pop:function(){//...}
}
Problem here: We lose the privacy of list and index.
Is there a way, such that we can have both methods reuse among instances and privacy of properties ?
I understand that we can have this for methods that don't operate on any state of the object, but I am talking more about those methods that do operate on the state.
Yes. I've edited this code so it's actually fully functional as you had intended it to work. It seems a bit redundant to me, but, it does provide you the ability to provide a public interface, but to keep your variables private and control the way the user interacts with them.
function MyStack(){
var list = [];
var index = 0;
this.getIndex = function(){
return index;
}
this.setIndex = function(val){
index = val;
}
this.list = function(val){
if(val){
// setter if a value was provided. Illustrating how you can control
// index, which I assume is the point of having these things private
// to begin with
return list[this.setIndex(this.getIndex() + 1)] = val;
}
// always return list - acts like a getter
return list;
}
}
MyStack.prototype = {
insert: function(val){
return this.list(val);
},
pop:function(){}
}
var stack1 = new MyStack();
stack1.insert(5);
var stack2 = new MyStack();
stack2.insert(11);
You should check out John Resig's Simple Javascript Inheritance. It is a great read, and it has been extended to provide support for privates, aptly called Privates.js;
A constructor function may return any object (not necesserily this). One could create a constructor function, that returns a proxy object, that contains proxy methods to the "real" methods of the "real" instance object. This may sound complicated, but it is not; here is a code snippet:
var MyClass = function() {
var instanceObj = this;
var proxyObj = {
myPublicMethod: function() {
return instanceObj.myPublicMethod.apply(instanceObj, arguments);
}
}
return proxyObj;
};
MyClass.prototype = {
_myPrivateMethod: function() {
...
},
myPublicMethod: function() {
...
}
};
The nice thing is that the proxy creation can be automated, if we define a convention for naming the protected methods. I created a little library that does exactly this: http://idya.github.com/oolib/
I think in both approaches you mentioned, When ever object is created using constructor pattern the properties will get copied to its objects. This you mentioned for the 1st approach as the concern. I feel the same will be applied for the second approach also along with your concern in this approach.
We generally go to the second approach you mentioned when ever we want to extend the properties of "MyStack" to some other class.
Lets say i want to extend your class MyStack to MyTest like below
var dummy = function();
dummy.prototype = MyStack.prototype;
var MyTest = function(){
};
MyTest.prototype = new dummy(); // Assigning MyStack properties to MyTest
var obj = new MyTest();

Question about the efficiency of closure/encapsulation in JavaScript

I'm somewhat new to JavaScript, so bear with me if this is a dumb question.
Let's say that I've got a "class" that looks like this:
var obj = function () {
var val;
return {
setVal: function(newVal) {
val = newVal;
},
getVal: function() {
return val;
}
};
};
Assuming my syntax is correct, this defines a class with a "private" property named "value," with methods to set/get the property. Now, I will create two objects from this class:
var myObj = obj();
var yourObj = obj();
Does this create a separate setVal() and getVal() method for each object? If not, why not? If so, is this a serious concern when building efficient web applications? Is the trade-off (if any) of efficiency for closure worth it in most/all contexts? Am I dumb?
Thanks,
Gerard
var obj = function () {
var val;
return {
setVal: function(newVal) {
val = newVal;
},
getVal: function() {
return val;
}
};
};
what this function does is as following :
create variable named val
create new object
create a new function and assign it to field setVal
create a new function and assign it to field getVal
return object.
So your always creating 4 new things.
This isn't really a problem if you have less then a 1000 objects on the page. Refactoring it away is a micro optimisation.
The alternative would be to not rely on local variables and use this._val to indicate that val is private.
It does do so conceptually. However, since this is such a common pattern, modern JavaScript JITers know how to optimize it away so that there is only one copy of the code stored in memory, with appropriate pointer redirections to make it work with the relevant closure.
EDIT: although I am not really up for spelunking through source code, here's some basic proof. Download the Chrome dev channel release, and take heap snapshots before and after running the following code:
var obj = /* as above */;
var objs = [];
for (var i = 0; i < 10000; ++i) {
objs.push(obj());
}
Then do the same for this code:
function Obj() { }
Obj.prototype.setVal = function (value) { this._val = value; };
Obj.prototype.getVal = function () { return this._val; };
var objs = [];
for (var i = 0; i < 10000; ++i) {
objs.push(new Obj());
}
You will find the heap snapshots to show the same numbers for "Code" in both cases, so indeed the optimization I describe is being performed.

How should I look at structuring my JavaScript?

I'm having a little trouble working out how my JavaScript should be structured, etc..
My OOP skills in languages such as PHP, ActionScript 3 and so on are what I'm assuming to be on-par, but JS is lacking this which has thrown me off quite a bit in my learning.
I have a vague understanding of the prototype feature which I used a little in AS2 - I believe this is the closest I'll be able to get. At the moment, I'm laying out my code similar to this:
var slideshow =
{
property: value,
/**
* This is a method
*/
myMethod: function()
{
// do method things
}
};
// ------
slideshow.property ++;
slideshow.myMethod();
This all works okay, but it's void my ability to do something like:
var myslideshow1 = new Slideshow();
var myslideshow2 = new Slideshow();
myslideshow1.property = 10;
myslideshow2.property = 16;
I'm not sure on how to go about creating two different instances of one "object" I've created (in this case, slideshow).
I can't find any resources that explain the prototype feature in a way that makes sense.
Any pointers would be supoib.
Any javascript function can act as a constructor for a class, so try this:
function SlideShow(params) {
return {
property: value,
myMethod: function() {
//do method things
};
};
};
var slideshow1 = new SlideShow(params);
slideshow1.property = 10;
//etc.
I would frown apon using prototype to add methods to a class as there could be performance issues
Here is a sample class structure you could use. JavaScript classes are not much different the functions.
function MyItem(){
this.d = '';
this.clear = function( ) {
this.d = '';
}
}
var myItem = new MyItem( )
myItem.d = "test";
alert(myItem.d);
myItem.clear();
alert(myItem.d)
Some good reading here
You should avoid using the new operator, everything is public. A better way to do what you want to do, and have private variables and functions is to do the following:
var slideshow = function () {
var self = {};
var private_param = "hello";
var private_func = function(say) {
alert(say);
};
var method = function() {
private_func(private_param);
};
var param = 500;
self.method = method;
self.param = param;
return self;
// return object, with the method func and param param publicly accessible
// private_param and private_func are not accessible to the outside
};
var presentation = slideshow(); // new slideshow, you could edit to pass in init params
presentation.method(); // hello

Categories