I'm trying to create a var with a couple of empty property's in it using JavaScript. In other languages (for sure in swift, but I'm sure in others too,) this is called a struct.
What I want it to look like is something like this:
myStruct {
value1 : String,
value2 : String
}
The closest I found to that is objects (JavaScript Objects), but with that you would have to add values (to my knowledge).
After, I need to add myStruct to an array. I hope this is clear. What is the most efficient way to achieve this?
Method 1:
The simplest of achieving this is to use new in combination with the Function constructor.
var myStruct = function(prop1,prop2){
this.prop1 = prop1;
this.prop2 = prop2;
}
var myStructObj = new myStruct();
var myStructObj2 = new myStruct("prop1","prop2");
var myArr = [];
myArr.push(myStructObj);
myArr.push(myStructObj2);
console.log(myArr);
An enhancement would be to add default params to the constructor and pass arguments while creation.
var myStruct = function(arg1, arg2){
var prop1 = arg1 || "defaultProp1Value";
var prop2 = arg2 || "defaultProp2Value";
this.prop1 = prop1;
this.prop2 = prop2;
}
var myStructObj1 = new myStruct();
//myStructObj1.prop1 is "defaultProp1Value"
//myStructObj1.prop2 is "defaultProp2Value"
var myStructObj2 = new myStruct("prop1");
//myStructObj2.prop1 is "prop1"
//myStructObj2.prop2 is "defaultProp2Value"
var myArr = [];
myArr.push(myStructObj1);
myArr.push(myStructObj2);
With ES6, you can do this, you can now add default parameters to the constructor.
//This only works in ES6
// Will cause errors on browsers which have not yet added support
// WIll work when used along with a transpiler like Babel
var myStruct = function(arg1 = "defaultProp1", arg2 = "defaultProp2"){
this.prop1 = arg1;
this.prop2 = arg2;
}
var myStructObj1 = new myStruct();
//myStructObj1.prop1 is "defaultProp1Value"
//myStructObj1.prop2 is "defaultProp2Value"
var myStructObj2 = new myStruct("prop1");
//myStructObj2.prop1 is "prop1"
//myStructObj2.prop2 is "defaultProp2Value"
var myArr = [];
myArr.push(myStructObj1);
myArr.push(myStructObj2);
console.log(myArr);
You can read more about it here
Method : 2
Using call method. With this approach you can add props on the fly. Whenever you want to add a couple of props to an object with either null values or default values you can use this approach.
var addPropsFunction = function(a,b){
this.prop1 = a;
this.prop2 = b;
}
var myObj1 = {};
var myObj2 = {};
addPropsFunction.call(myObj1);
addPropsFunction.call(myObj2,"val1","val2");
console.log(myObj1);
console.log(myObj2);
Method : 3
ES6 Classes
class myStruct{
constructor(prop1,prop2){
this.prop1 = prop1;
this.prop2 = prop2;
}
}
var myObj = new myStruct();
console.log(myObj);
Es6 Fiddle - http://www.es6fiddle.net/ifz3rjcc/
In all cases, changing properties is the same.
To change prop1's value, all you have to do is
myStructObj.prop1 = "my val";
null is a value which means "no value". Assigning null to your properties yields exactly what you need.
Well you could do
var myArray = [
{"value1":"Value1Here", "value2":"Value2Here"},
{"value1":"Value1Here", "value2":"Value2Here"},
{"value1":"Value1Here", "value2":"Value2Here"}
];
(these values can be null)
or you could declare your object as above
and do :
myArray.push(yourObject)
I think by now you know how to create a struct in JS.
Now, to initialize properties with empty values:
You have to use either null or undefined based on your requirement.
These links can help you in understanding what and how exactly you have to proceed.
null and undefined
Which one to use?
Related
I'm trying to make an array object that can set itself.
Something like this...
array = new Array(10)
array.someMethod = function () {
this = new Array(20)
}
Except this doesn't work because this can't be set like that.
More or less I want an object that I use array[index] on.
Seems to me this could be accomplished by using an object and storing the array in one of the object's properties. I'm learning about the class syntax, so I did it that way, but I think the same approach would work with regular objects.
class MyArray {
constructor(num) {
console.log(`building MyArray with ${num} objects`);
this.innerArray = new Array(num);
}
update(num) {
console.log(`updating MyArray to have ${num} objects`);
this.innerArray = new Array(num);
}
get() { return this.innerArray }
}
let foo = new MyArray(10);
foo.get()[0] = "bar";
console.log(foo.get());
foo.update(20);
foo.get()[0] = "baz";
console.log(foo.get());
the way you asked your question is not quite right you should explain better.
not sure this is what you want.
you can't change the this in javascript.
but function in prototype will be called with the object as their context. so Array.prototype.length gives the length in arr.length by having arr as it's context. Array.prototype.splice
so
Array.prototype.testA = function() {
// this.splice(0,this.length);
var a = [3,5,7];
// new Array(23).fill().map( (a,_)=>_)
this.splice(0,this.length,...a);
}
Array.prototype.testAA = function() {
var a = [3,5,7];
this.splice(this.length,0,...a);
}
var a = [1];
a.testAA();
console.log(a);
a.testA();
console.log(a);
I am in the final stages of a game development and i have a bunch of objects like this;
roomBedroom = function () {
this.title = "Bedroom";
this.description = "I'm in a bedroom";
this.noun = "bed";
this.entities = new Array();
}
var bedroom = new roomBedroom();
What I want to do now is place all of my game objects into an array;
var savedGameObjects = {};
savedGameObjects['bedroom'] = bedroom;
var jsonGame = JSON.stringify(savedGameObjects);
The plan is to then save the savedGameObjects array and then recall it when the user loads the game again.
If I replace savedGameObjects['bedroom'] = bedroom; with savedGameObjects['bed'] = 'slappy'; it works but not when I have the object.
I really need to save the objects in their current state. I'd rather not go through each object saving key pieces of information one by one.
This feels like a bit of a hack, but its the best I can come up with right now
Your serialization/deserializtion utility
This is going to attach obj.constructor.name to obj.__prototype before serialization. Upon deserializing, the prototype will be put back in place.
(function(global) {
function serialize(obj) {
obj.__prototype = obj.constructor.name;
return JSON.stringify(obj);
};
function deserialize(json) {
var obj = JSON.parse(json);
obj.__proto__ = global[obj.__prototype].prototype;
return obj;
}
global.serialize = serialize;
global.deserialize = deserialize;
})(window);
A sample "class"
(function(global) {
function Foo() {
this.a = "a";
this.b = "b";
}
Foo.prototype.hello = function() {
console.log("hello");
}
global.Foo = Foo;
})(window);
Let's try it out
var foo = new Foo();
var json = serialize(foo);
console.log(json);
var newFoo = deserialize(json);
console.log('a', newFoo.a); // a
console.log('b', newFoo.b); // b
newFoo.hello(); // hello
Watch out for some gotchas
If you use an expression to define your "class", you will have a nameless constructor
var Foo = function() {};
var foo = new Foo();
foo.constructor.name; // ""
As opposed to a named function
function Foo() {}
var foo = new Foo();
foo.constructor.name; // Foo
In order for serialize and deserialize to work, you will need to use named functions
Another gotcha
The deserialize method expects your "classes" to exist on the in the same namespace (window in this case). You could encapsulate your game object classes in another way, just make sure that you reconfigure the deserialize method so that it can find the prototypes as needed.
Making this better
Instead of attaching serialize to the global window, you could have serialize live on (e.g.) the GameObject.prototype then your individual classes could inherit from GameObject. Serializing an object would then be as simple as
var json = foo.serialize();
// {"a":"a","b":"b","__prototype":"Foo"}
You could then define deserialize as GameObject.deserialize and restoring foo would be
var foo = GameObject.deserialize(json);
An alternative solution
Instead of implementing a custom serializer and deserializer, you could make very clever use of the Factory Method Pattern.
This might be a little verbose, but it does give you individual control over how a game object should be deserialized/restored.
var savedData = // your normal JSON here
var player = Player.create(savedData.player);
var items = [];
for (var i=0, i<savedData.items.length; i++) {
items.push(Item.create(savedData.items[i]));
}
var map = Map.create(savedData.map);
This was a pretty interesting problem and I'm sure you're not the first to encounter it. I'm really curious to see what other people come up with.
If I run the following code in a browser there is no problem getting the JSON string of the bedroom object, not sure what the problem is.
Note that JSON is data and bedroom is an object, bedroom may have behaviour like turnOffLight() that JSON doesn't have.
roomBedroom = function () {
this.title = "Bedroom";
this.description = "I'm in a bedroom";
this.noun = "bed";
this.entities = new Array();
}
var bedroom = new roomBedroom();
var savedGameObjects = {};
savedGameObjects['bedroom'] = bedroom;
//logs {"bedroom":{"title":"Bedroom","description":
// "I'm in abedroom","noun":"bed","entities":[]}}
console.log(JSON.stringify(savedGameObjects));
So if you want to re create object instances from JSON data then you can change your constructor:
roomBedroom = function (args) {
//following fails fast and loud, you could silently
//fail by setting args to {}
if(typeof args!=="object")
throw new Error("Have to create roomBedroom by passing an object");
//or do args={} to silently fail
this.title = args.title||"Bedroom";
this.description = args.description||"I'm in a bedroom";
this.noun = args.noun||"bed";
//if entities are objects with behavior
// you have to re create them here passing the JSON data
// as I've done with roomBedroom
this.entities = args.entities||new Array();
}
var jsonString='{"bedroom":{"title":"Bedroom",'+
'"description":"I\'m in a bedroom",'+
'"noun":"bed","entities":[]}}';
var bedroom = new roomBedroom({});
bedroom.entities.push({hi:"there"});
bedroom.title="Master Bedroom";
//serialize bedroom to a json string
var jsonString = JSON.stringify(bedroom);
//create a roomBedroom instance named br2 using
// the serialized string
var br2=new roomBedroom(JSON.parse(jsonString));
//compare if they are the same
console.log(JSON.stringify(bedroom)===JSON.stringify(br2));//true
I have an approach that might work for you. You can see it in action on JSFiddle.
The main point is to use the reviver parameter to JSON.parse to reconstruct your object when it's parsed.
I do this with a general-purpose reviver that can be configured for multiple different types, although here the only one used is the RoomBedroom constructor. This implementation assumes that you have simple copy constructors that create new objects using a reference to an existing one. (For other, more sophisticated possibilities, see an answer to another question I gave in February.) To make it easy to have a copy constructor, I have one more function that accepts a very simple constructor function and a set of default values and builds a copy constructor function for you.
var MultiReviver = function(types) {
return function(key, value) {
var type;
for (var i = 0; i < types.length; i++) {
type = types[i];
if (type.test(value)) {
return new type.constructor(value);
}
}
return value;
};
};
var makeCloningConstructor = (function() {
var clone = function(obj) {return JSON.parse(JSON.stringify(obj));};
var F = function() {};
return function(Constructor, defaults) {
var fn = function(obj) {
Constructor.call(this);
var self = this;
var config = obj || {};
Object.keys(defaults).forEach(function(key) {
self[key] = clone(defaults[key]);
});
Object.keys(config).forEach(function(key) {
self[key] = clone(config[key]);
});
};
F.prototype = Constructor.prototype;
fn.prototype = new F();
fn.constructor = Constructor;
return fn;
};
})();
// Note: capitalize constructor functions
var RoomBedroom = makeCloningConstructor(function RoomBedroom() {}, {
title: "Bedroom",
description: "I'm in a bedroom",
noun: "bed",
entities: [] // Note: use `[]` instead of `new Array()`.
});
RoomBedroom.prototype.toggleLight = function() {
this.lightOn = !this.lightOn;
};
RoomBedroom.prototype.checkLights = function() {
return "light is " + (this.lightOn ? "on" : "off");
};
var bedroom = new RoomBedroom();
bedroom.windowCount = 3; // add new property
bedroom.noun = "king-sized bed"; // adjust property
bedroom.toggleLight(); // create new propery, use prototype function
console.log(bedroom.checkLights());
var savedGameObjects = {};
savedGameObjects['bedroom'] = bedroom;
var jsonGame = JSON.stringify(savedGameObjects);
var reviver = new MultiReviver([{
constructor: RoomBedroom,
test: function(obj) {
var toString = Object.prototype.toString, str = "[object String]",
arr = "[object Array]";
return toString.call(obj.title) == str &&
toString.call(obj.description) == str &&
toString.call(obj.noun) == str &&
toString.call(obj.entities) == arr;
}
}]);
var retrievedGameObjects = JSON.parse(jsonGame, reviver);
// data comes back intact
console.log(JSON.stringify(retrievedGameObjects, null, 4));
// constructor is as expected
console.log("Constructor: " + retrievedGameObjects.bedroom.constructor.name);
// prototype functions work
console.log(retrievedGameObjects.bedroom.checkLights());
I don't know if it's precisely what you were looking for, but I think it's at least an interesting approach.
the faster route
It is better — from an optimisation point of view — to do as Adeneo states, which is power each of your Game Objects by an exportable simple object i.e:
roomBedroom = function(){
this.data = {};
this.data.title = 'Bedroom'
/// and so on...
}
These can then be easily stored and re-imported just by JSON.Stringifying and overwriting the data property. For example, you could set-up the system that Maček mentions (+1) which is to give each of your game objects serialize and deserialize functions:
roomBedroom.prototype.serialize = function(){
return JSON.stringify( this.data );
};
roomBedroom.prototype.deserialize = function( jstr ){
this.data = JSON.parse(jstr);
};
the quicker way
However, you can make a simple addition to what you already have using the following:
First enhance your Game Objects with an objectName property. This is because constructor.name and function.name are unreliable and do strange things the further back in time you go, far better to use a string you have set in stone.
var roomBedroom = function ( title ) {
this.objectName = "roomBedroom";
this.title = title;
this.description = "I'm in a bedroom";
this.noun = "bed";
this.entities = new Array();
};
Then the additional code to help with storage:
var storage = {};
/// add your supported constructors to this list, there are more programmatic
/// ways to get at the constructor but it's better to be explicit.
storage.constructors = {
'roomBedroom' : roomBedroom
};
/// take an instance and convert to simple object
storage.to = function( obj ){
if ( obj.toStorage ) {
return obj.toStorage();
}
else {
var keep = {};
for ( var i in obj ) {
if ( obj.hasOwnProperty(i) && !obj[i].call ) {
keep[i] = obj[i];
}
}
return keep;
}
}
/// take simple object and convert to an instance of constructor
storage.from = function( obj ){
var n = obj && obj.objectName, c = storage.constructors[n];
if ( n && c ) {
if ( c.fromStorage ) {
return c.fromStorage( obj );
}
else {
var inst = new c();
for ( var i in obj ) {
if ( obj.hasOwnProperty(i) ) {
inst[i] = obj[i];
}
}
return inst;
}
}
else {
throw new Error('`' + n + '` undefined as storage constructor');
}
}
Once you have that you can use it like so:
var savedGameObjects = {};
savedGameObjects['bedroom'] = storage.to(new roomBedroom("bedroom"));
savedGameObjects['bedroom2'] = storage.to(new roomBedroom("bedroom2"));
var jsonGame = JSON.stringify(savedGameObjects);
console.log(jsonGame);
savedGameObjects = JSON.parse(jsonGame);
for( var i in savedGameObjects ) {
savedGameObjects[i] = storage.from(savedGameObjects[i]);
console.log(savedGameObjects[i]);
}
extras
You can also be specific about the way objects get stored/unstored by supplying toStorage and fromStorage methods on your constructed instances and constructors respectively. For example, you could use the following if you only wanted to store titles of roomBedrooms. Obviously this is an unrealistic use-case, you'd more often use this to avoid storing cached or computed sub-objects and properties.
roomBedroom.prototype.toStorage = function( obj ){
var ret = {};
ret.title = obj.title;
return ret;
};
roomBedroom.fromStorage = function( obj ){
var inst = new roomBedroom();
inst.title = obj.title;
return inst;
};
The above also means you can take advantage of improving your Game Object construction by providing parameters, rather than iterating over properties which can be slow and error-prone.
roomBedroom.fromStorage = function( obj ){
return new roomBedroom( obj.title );
};
Or even:
roomBedroom.fromStorage = function( obj ){
return new roomBedroom( obj ); // <-- the constructor processes the import.
};
fiddle
http://jsfiddle.net/XTUdp/
disclaimer
The above code relies on the existence of hasOwnProperty which is not present cross-browser yet, a polyfill should be used until it is... or, if you aren't doing anything complicated with prototype inheritance you don't need to worry and can remove it from the code.
you can declare a big variable like
var world = {};
and each small variable declare as
var bedroom = world.bed = (world.bed || new roomBedroom());
remember never change bedroom to another object, i think this will work fine, but looks too long winded
Suppose I create a custom object/javascript "class" (airquotes) as follows:
// Constructor
function CustomObject(stringParam) {
var privateProperty = stringParam;
// Accessor
this.privilegedGetMethod = function() {
return privateProperty;
}
// Mutator
this.privilegedSetMethod = function(newStringParam) {
privateProperty = newStringParam;
}
}
Then I want to make a list of those custom objects where I can easily add or remove things from that list. I decide to use objects as a way to store the list of custom objects, so I can add custom objects to the list with
var customObjectInstance1 = new CustomObject('someString');
var customObjectInstance2 = new CustomObject('someOtherString');
var customObjectInstance3 = new CustomObject('yetAnotherString');
myListOfCustomObjects[customObjectInstance1] = true;
myListOfCustomObjects[customObjectInstance2] = true;
myListOfCustomObjects[customObjectInstance3] = true;
and remove custom objects from the list with
delete myListOfCustomObjects[customObjectInstance1];
but if i try to iterate through the list with
for (i in myListOfCustomObjects) {
alert(i.privilegedGetMethod());
}
I would get an error in the FireBug console that says "i.privilegedGetMethod() is not a function". Is there a way to fix this problem or an idiom in javascript to do what I want? Sorry if this is a dumb question, but I'm new to javascript and have scoured the internet for solutions to my problem with no avail. Any help would be appreciated!
P.S. I realize that my example is super simplified, and I can just make the privateProperty public using this.property or something, but then i would still get undefined in the alert, and I would like to keep it encapsulated.
i won't be the original object as you were expecting:
for (i in myListOfCustomObjects) {
alert(typeof i); // "string"
}
This is because all keys in JavaScript are Strings. Any attempt to use another type as a key will first be serialized by toString().
If the result of toString() isn't somehow unique for each instance, they will all be the same key:
function MyClass() { }
var obj = {};
var k1 = new MyClass();
var k2 = new MyClass();
obj[k1] = {};
obj[k2] = {};
// only 1 "[object Object]" key was created, not 2 object keys
for (var key in obj) {
alert(key);
}
To make them unique, define a custom toString:
function CustomObject(stringParam) {
/* snip */
this.toString = function () {
return 'CustomObject ' + stringParam;
};
}
var obj = {};
var k1 = new CustomObject('key1');
var k2 = new CustomObject('key2');
obj[k1] = {};
obj[k2] = {};
// "CustomObject key1" then "CustomObject key2"
for (var key in obj) {
alert(key);
}
[Edit]
With a custom toString, you can set the object as the serialized key and the value to keep them organized and still continue to access them:
var customObjectInstance1 = new CustomObject('someString');
var customObjectInstance2 = new CustomObject('someOtherString');
var customObjectInstance3 = new CustomObject('yetAnotherString');
myListOfCustomObjects[customObjectInstance1] = customObjectInstance1;
myListOfCustomObjects[customObjectInstance2] = customObjectInstance2;
myListOfCustomObjects[customObjectInstance3] = customObjectInstance3;
for (i in myListOfCustomObjects) {
alert(myListOfCustomObjects[i].privilegedGetMethod());
}
The for iteration variable is just the index, not the object itself. So use:
for (i in myListOfCustomObjects) {
alert(myListOfCustomObjects[i].privilegedGetMethod());
}
and, in my opinion, if you use an Object as an array index / hash, it just would be converted to the string "Object", which ends up in a list with a single entry, because all the keys are the same ("Object").
myListOfCustomObjects =[
new CustomObject('someString'),
new CustomObject('someOtherString'),
new CustomObject('yetAnotherString')
]
you will get access to any element by index of array.
I've been learning more about javascript's prototypal inheritance. I know there is a somewhat fierce debate on whether to extend native objects and I'd like to side step that whole debate entirely in this question.
Is it possible to extend only descendent object in javascript?
To extend all objects I can do this:
Object.prototype.size = function(){
var length = 0;
for(var i in this){
if(this.hasOwnProperty(i)){
length++;
}
}
return this;
}
But the problem is that It extends all objects. What I'd like to do is have this:
var MyNameSpace = function(){
};
MyNameSpace.Object.prototype.size = function(){
var length = 0;
for(var i in this){
if(this.hasOwnProperty(i)){
length++;
}
}
return this;
}
That way I would only be extending the native objects in the scope of my global object.
any suggestions would be great thanks
Update:
In response to a few comments I'm adding more code to clarify what I'm trying to do.
I think i may have not phrased my question correctly, or maybe my thinking is incorrect, but what i'd like to be able to do is this:
var my = new MyNameSpace();
var my.name = {firstName : 'Hello', lastName : 'World'};
var nameCount = my.name.size(); // 2
the code you provided will allow me to get the size of each MyNameSpace object I create, but not the object literals that are properties of the MyNameSpace object
You could use "pseudo-classical" inheritance style to achieve it:
var MyNameSpace = function() {
this.v1 = null;
this.v2 = null;
}
MyNameSpace.prototype.size = function() {
var length = 0;
for(var i in this){
if(this.hasOwnProperty(i)){
length++;
}
}
return this;
}
var my = new MyNameSpace(); // create new object based on MyNameSpace
my.size(); // length would be 2
What you define on a function object's prototype would be inherited by all the function objects created via new operator.
Updated code, according to your added requirements,
var obj = {};
var MyNameSpace = function(props) {
for(var name in props) {
this[name] = props[name];
}
}
MyNameSpace.prototype.size = function() {
var length = 0;
for(var i in this){
if(this.hasOwnProperty(i)){
length++;
}
}
return this;
}
obj.name = new MyNameSpace({firstName : 'Hello', lastName : 'World'});
obj.name.size(); // length would be 2
In your code
var my = new MyNameSpace();
var my.name = {firstName : 'Hello', lastName : 'World'};
var nameCount = my.name.size(); // 2
my.name is obviously traversable from my, but the opposite is not true. That means that properties of my cannot be accessed from my.name, and my is nowhere to be found in the prototype chain of my.name. If you don't want to inherit directly from MyNameSpace you have to explicitly "hang on" whatever functions you would like to inherit.
You could do
my.name.size = my.size;
alternatively (without having to instantiate MyNameSpace):
my.name.size = MyNameSpace.prototype.size;
if you have only few functions to "inherit". Or you could define an inherit function in MyNameSpace as follows:
MyNameSpace.prototype.addToNameSpace = function(obj) {
obj.size = this.size;
// obj.propertyI = this.propertyI, etc.
}
Note that I don't use for..in here as that would add the addToNameSpace function as well.
Hope this helps
What is the cleanest format for writing javascript objects?
Currently I write mine in the following format
if (Namespace1 == null) var Namespace1 = {};
if (Namespace1.NameSpace2 == null) Namespace1.NameSpace2 = {};
Namespace1.NameSpace2.Class1 = function(param1,param2){
// define private instance variables and their getters and setters
var privateParam = param1;
this.getPrivateParam = function() {return privateParam;}
this.publicParam1 = param2;
}
Namespace1.Namespace2.Class1.prototype = {
publicParam1:null,
publicFunction1:function() {/* Function body*/}
}
That format works well right now, as the YUI documentation software is able to parse it, and the comments and give back good documentation. But what it doesn't provide is a clean way to declare static global methods within the namespace. I am also wondering if there is a cleaner way to declar private variables as well.
My question is, is anyone out there have a cleaner way of defining javascript objects than this, and if so, why is your method better?
Thanks!
The module pattern may help you out here:
var Namespace1 = Namespace1 || {};
Namespace1.Namespace2 = Namespace1.Namespace2 || {};
Namespace1.Namespace2.Class1 = function(param1, param2) {
// define private instance variables and their getters and setters
var privateParam = param1;
this.getPrivateParam = function() { return privateParam; }
this.publicParam1 = param2;
return {
init: function() {
alert('hi from Class1');
}
}
} ();
You can read more about it here: http://yuiblog.com/blog/2007/06/12/module-pattern/
Namespace1.Namespace2.Class1.init();
First of all, if you don't know if Namespace1 is defined, use typeof this.Namespace1 !== "undefined", as accessing Namespace1 will throw an error if it's not defined. Also, undefined properties are undefined, not null (though undefined == null). Your check will fail if something is actually null. If you don't want to use typeof for checking if properties are undefined, use myObject.property === undefined.
Also, your second example has invalid syntax. Here is what I think you wanted to do:
Namespace1.Namespace2.Class1.prototype = {
publicParam1 : null,
publicFunction1 : function () {/* Function body*/}
};
Certainly rewrite the first two lines to this:
var Namespace1 = Namespace1 || {};
Namespace1.Namespace2 = Namespace1.Namespace2 || {};
The rest of the looks ok. The private variable is pretty much how everyone does it. Static methods should be assigned to the prototype, as you have done.
Do take care redefining the entire prototype for an object though, since it will prevent you from a common pattern of prototype-based inheritance. For instance:
// You inherit like this...
Sub.prototype = new Super();
obj = new Sub();
// Then you overwrite Sub.prototype when you do this:
Sub.prototype = {foo:1, bar:2}
// Instead, you should assign properties to the prototype individually:
Sub.prototype.foo = 1;
Sub.prototype.bar = 2;
I use the following function:
jQuery.namespace = function() {
var a = arguments, o = null, i, j, d;
for (i=0; i<a.length; i=i+1) {
d = a[i].split(".");
o = window;
for (j=0; j<d.length; j=j+1) {
o[d[j]] = o[d[j]] || {};
o = o[d[j]];
}
}
return o;
}
Then I can use this function to create a namespace just like this:
$.namespace("jQuery.namespace1");
Once I've created the namespace I can declare functions or whatever you want inside it:
a function:
$.namespace1.asyncRequest = function() {
[function body]
};
a constant:
$.namespace1.OFFSET = 10;
an object:
$.namespace1.request = { requestId: 5, protocol: 'JSON' };
I think it's simple and elegant :-)
Bye,
Alex