Javascript nested objects - javascript

I'm trying todo some OO in Javascript, and I'm coming from C++ and Ruby. I've managed to create one object, but nesting an object inside is being alittle bit of a pain.
function Model()
{
//...
}
function Player(props)
{
var props = {
// ...
}
var model = new Model(props); // I've tried 'this.model = new Model() as well
}
var props = {
// ...
}
var player = new Player(props);
Player gets created fine, but if I try and nest the object it fails. What am I doing wrong.

Example
You were close. There are much better ways of "seudo-extending" object in javascript. jQuery.extend is one possible way. You can write your own method that check properties as well. I think the biggest break down for you was overwriting props in the Player function.
With functions this is key
Functions are the only scope in JavaScript, so be careful with naming variables
It's important to understand the difference between the object literal var a = {} and functions var a = new Method();. However, it seems you have that down well.
Code
function Model(data)
{
this.Name = data.Name;
this.Other = data.Other;
}
function Player(props)
{
var privateProps = {
Name: 'testing'
};
privateProps.Other = props.Other;
this.model = new Model(privateProps); // I've tried 'this.model = new Model() as well
}
var props = {
Other: 'Other'
}
var player = new Player(props);
​

Related

Classes inside object literals

I was just not sure how to search this out despite many tries, so forgive me if this has been answered before.
The question is simple: can I create an instance of class window.A.class() as window.B?
To clarify, I have an object literal holding all my data for a browser game:
var gameName = {
environment: function() {
this.place = "...";
// ...
// ...
},
game: function() {
this.player = function() {
// ...
}
}
// and so on...
}
Could I create a window-level gameName.environment() instance with var A = new gameName.environment()? Are there any restrictions to creating an object-bound class's instance outside the class' parent object?
It doesn't really matter in this case how/where a function is defined. Consider these two examples:
function Foo() {}
var obj = {
bar: Foo
};
and
var obj = {
bar: function () { }
};
As far as the function and the object are concerned, those two examples are equivalent. So no, there is no problem calling a function assigned to an object property with new. All you need is a reference to the function, it doesn't matter how you get that reference.
You could do
var Environment = gameName.environment;
var A = new Environment();
if you like that better, but that's totally unnecessary.

Reorganising a lot of methods built on the prototype chain

I've started to write some code to implement a simple game in JavaScript. The basic idea is that dealer.game holds a bunch of objects (player,hand,funds etc) which hold the current state of the game. Then I have various methods which manipulate these objects. I've chosen to use the prototype chain as there could be multiple instances of the dealer.game instance so I wanted shared methods between these instances.
working fiddle:
http://jsfiddle.net/BhPrQ/
and the code:
dealer = {}
dealer.game = function() {
this.player = {};
this.hand = {};
this.set = {};
this.funds = {};
this._drawBoard();
};
dealer.game.prototype._drawBoard = function() {
//draw board in svg here
};
dealer.game.prototype.addPlayer = function(name,funds) {
this.setFunds(name,funds);
this._drawPlayer(name);
};
dealer.game.prototype._drawPlayer = function(name) {
this.player[name] = '';
};
dealer.game.prototype._getPlayer = function(name) {
this.player[name] = '';
};
dealer.game.prototype.setFunds = function(name,funds) {
this.funds[name] = funds;
};
dealer.game.prototype.removeFunds = function() {
};
dealer.game.prototype.drawFunds = function() {
};
var poker = new dealer.game();
poker.addPlayer("jenny",200);
poker.addPlayer("jack",100);
console.log(poker.player);
console.log(poker.funds);
The problem I'm seeing straight away is with even this minimal boilerplate of code adding methods to the object via the prototype chain is going to become messy. I've got a bunch of methods that do stuff to the player and then more that do stuff to the funds...as this grows I can see that I'm going to end up with a huge amount of methods directly linked off the prototype chain which are all mixed in terms of what they do. I know there's technically nothing wrong with this but Is there are better way to organise this? I considered separate objects that require instantiation...something like:
dealer.funds = function() {
};
dealer.funds.prototype.addFunds = function() {
};
But the problem with this is that the instantiated funds object will no longer have access to the core player,hand,set or funds objects contained within player.game.
How do I reorganise this?
The answer was staring me in the face. Create separate classes for the separate parts of my application:
dealer = {};
dealer.game = function() {
this.player = {};
};
dealer.game.prototype.addPlayer = function(name,funds) {
//assign the object returned by dealer.player to my game.player object
//this way my application always has access to all players that have been created
this.player[name] = new dealer.player();
};
dealer.player = function() {
//do some stuff and then return the object
return this;
};

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();

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

JavaScript: Public methods and prototypes

I'm not entirely sure how to implement OOP concepts in JS.
I have a class which is entirely declared in its constructor:
function AjaxList(settings)
{
// all these vars are of dubious necessity... could probably just use `settings` directly
var _jq_choice_selector = settings['choice_selector'];
var _jq_chosen_list = settings['chosen_list'];
var _cb_onRefresh = settings['on_refresh'];
var _url_all_choices = settings['url_choices'];
var _url_chosen = settings['url_chosen'];
var _url_delete_format = settings['url_delete_format'];
var jq_choice_selector_form = _jq_choice_selector.closest("form");
if (DEBUG && jq_choice_selector_form.length != 1)
{
throw("There was an error selecting the form for the choice selector.");
}
function refresh()
{
_updateChoicesSelector();
_updateChosenList();
_cb_onRefresh();
};
AjaxList.prototype.refresh = refresh; // will this be called on all AjaxLists, or just the instance used to call it?
// AjaxList.refresh = refresh; // will this be called on all AjaxLists, or just the instance used to call it?
// ...
}
There are multiple instances of AjaxList. When I call refresh() on one of them, I want only that one list to refresh itself. In the following instance:
term_list = AjaxList(settings);
term_list.refresh();
The refresh() call seems to make all the AjaxLists refresh themselves. What is the correct way to do this?
I'm using jQuery, if it makes any difference.
You should not redefine the prototype function in the constructor.
If you want to create a privileged function use this.methodname = ... from the constructor.
function AjaxList() {
var privateVar = 0;
function privateFunction() {
//...
}
//create a refresh function just for this instance of the AjaxList
this.refresh = function() {
//privileged function, it can access the 'privateVar & privateFunction'
privateVar++;
}
}
//public functions that don't need access to the private variables/functions
AjaxList.prototype.publicFunction=function() {
};
Also if you want to create a proper object, you need to change
term_list = AjaxList(settings);
to
term_list = new AjaxList(settings);
AjaxList = function(settings) {
this._jq_choice_selector = settings["choice_selector"];
this._jq_chosen_list = settings["chosen_list"];
this._cb_onRefresh = settings["on_refresh"];
this._url_all_choices = settings["url_choices"];
this._url_chosen = settings["url_chosen"];
this._url_delete_format = settings["url_delete_format"];
this.jq_choice_selector_form = _jq_choice_selector.closest("form");
if (DEBUG && jq_choice_selector_form.length != 1) {
throw "There was an error selecting the form for the choice selector.";
}
};
AjaxList.prototype = {
_updateChoicesSelector: function() { },
_updateChosenList: function() { },
_cb_onRefresh: function() { },
refresh: function() {
this._updateChoicesSelector();
this._updateChosenList();
this._cb_onRefresh();
}
};
Given that structure, you should be able to call:
var ajaxList = new AjaxList(settings);
ajaxList.refresh(); // etc.
I'm using jQuery, if it makes any
difference.
No it doesn't. See my answer here: What's the difference between Javascript, Jquery and Ajax?
I have a class which is entirely
declared in its constructor
There are no classes in Javascript. Forget them. You really need to learn some of the basics of this language in order to use them. It's not Java, even though it looks similar.
If you have a Constructor Function it will create an instance. The shared methods will be in the prototype chain, and only instance specific data goes right into the function with the this keyword.
So the basic concept of an object would look like this:
// constructor of an instance
function MyObject( param1, param2 ) {
this.param1 = param1;
this.param2 = param2;
this.param3 = 32;
return this; // [optional]
}
// Public methods can be called by any instance.
// Instances share their prototype object.
// The this keyword always points to the current
// instance that calls the method.
MyObject.prototype.sum = function() {
return this.param1 + this.param2 + this.param3;
}
// refresh should be a shared method, since it
// does the same thing on every instance
MyObject.prototype.refresh = function() {
// do the refresh
// ...
}
The power of this concept is that there is only one refresh function in memory. And it can deal with any instance. In addition, if another object inherits from MyObject the refresh function will be inherited. But in the memory there will be still one shared refresh function. And it can deal with any of the parent or child instances.

Categories