I'm new to object oriented programming and am slowly learning how to apply it to javascript. So please bear with me. :)
I have two basic objects:
"record" which contains methods for editing a single record from a recordset. (create, save, load, etc.)
"recordList" which contains methods for outputting a paginated list of record titles.
I would like for these objects to be able to work together. For example, if record.save() is called, recordList.refresh() is also called, so that the paginated list reflects the updated data.
To accomplish this, I have created a third object "control" which contains instances of both "record" and "recordList". I am using "control" in the following fashion:
control = {}
control.record = object.create("record");
control.recordList = object.create("recordList");
control.save = function() {
this.record.save();
this.recordList.refresh();
};
This works. But I am wondering, is it proper? (I want to be sure I am not violating any of the rules of OO design in doing this.) Is there a better way?
Thanks in advance for your help.
Speaking from an OOP perspective, I don't think a record would save itself. A record in a database is simply data, and the database itself is what does things with that data, whether it's saving or loading or etc. That being said I'd make record be simply an object that holds data and would create a recordset object for interacting with the data. Within that recordset object you could put your recordList and update it accordingly. Something like:
var recordset = function() {
var me = this;
var currentRecord = object.create("record");
var recordList = object.create("recordList");
me.save = function() {
//Insert record.save code here
recordList.refresh();
};
};
Something to note about that code. In that setup currentRecord and recordList can't be accessed from outside the function and therefore you have encapsulation, one of the hallmarks of OOP. This is because the recordset function is a closure that "closes over" all variables within, meaning that every function within has access to the variables within the scope of recordset.
You could let the outside world get access through get or set functions:
me.getRecordList = function() {
return recordList.getArray(); //Not generally a good idea to simply return your internal object
};
Your solution is fine. Two minor suggestions for improvement
Use a more specific name than control (even 'recordControl' is ok). You may end up with lots of controls for different feature sets.
Use an object literal to create the entire object. Keeps your code tidier and more readable (and saves a few bytes)
(apologies for lack of spacing - editor not doing what I want it to do!)
recordControl = {
record : object.create("record"),
recordList : object.create("recordList"),
save : function() {
this.record.save();
this.recordList.refresh();
}
}
If it's one thing I've learned over time, it is that following any paradigm to the letter will result in more frustration and difficulty than taking the concept as far as you can go and using common sense to dictate your deviations.
That said, your solution will work fine and it's normal to create a container class for multiple objects of varying types that are coupled. If you want a different way to handle it, check out Client Event Pooling. The only thing that I can say about what you've done is to be sure you're using object.create the way it was intended.
Using this method you can create an event, which when triggered will perform a series of other commands that are associated with your event. I have used this with great success in all sorts of applications, from the intended event hooking to simplifying inline javascript injections after a postback.
Good luck.
why don't you provide your recordList into record?
var record = object.create("record");
record.recordList = object.create('recordList');
record.save = function(){
/*
do something
*/
this.recordList.refresh();
}
Related
I know people mostly refer to two-way binding when it comes to variables displayed in the HTML, but I keep running into this same problem and realized there is something fundamental about Angular that I'm not understanding.
To set up this question, I am currently developing an RPG browser game. I want each character to have baseStats which are represented as:
'baseStats' : {
'defense' : 5,
'strength' : 3,
'speed' : 7
}
but during the course of the battle, they may be 'buffed' or 'debuffed', so I want to be able to track those changes without permanently changing the characters stats, so baseStats exists to preserve the 'original' state of the stats.
vm.restoreAll = function() {
angular.forEach(vm.activeAllies, function(ally) {
ally.stats.defense = ally.baseStats.defense;
ally.stats.strength = ally.baseStats.strength;
ally.stats.strength = ally.baseStats.speed;
});
};
This works exactly as I intend it to. Each of these stats is reset to the baseStat
vm.restoreAll = function() {
angular.forEach(vm.activeAllies, function(ally) {
ally.stats = ally.baseStats;
});
}
This is obviously more readable and terse, but unfortunately if I make changes to ally.stats from elsewhere in the application, those changes affect the baseStats as well. I'm confused why this would be as they seem to be effectively the same exact thing.
Your issue is not really specific to Angular but Javascript in general. When you pass object values around to different variables you are not passing the actual object value but just a reference to the object. So the object value itself only exists in one place in memory and each variable holds a reference to that location.
This blog post explains further: http://nsono.net/javascript-pass-by-value-or-pass-by-reference/
As the other comments already explain using Angular's copy function will cause an entire new object to be created and stored in memory and fix your issue.
There are various non-Angular ways of cloning objects as well, some described here: http://heyjavascript.com/4-creative-ways-to-clone-objects/
Probably the most concise: JSON.parse(JSON.stringify(myObject))
I come from a C# background. I've been working a lot with JavaScript lately. On a new app, I have a mysql/php back end. I'm going to be passing a lot of "types" back and forth.
So in my data base, I have several tables like
table1
id, fieldx,fieldy,fieldz
table2
id, fielda,fieldb,fielc
In c# I would definitely write classes for all those in the code. Which led me to implement things like so (in my JavaScript app):
function table1(id, x,y,z){
this.id=id;
this.x=x;
this.y=y;
this.z=z;
}
After about 6 tables worth of that, it suddenly occurred to me that maybe there was no point at all in making these classes.
So my question is, in a JavaScript app, do I use "classes" for data types? or should I just "document" which fields/types are expected and so in the code instead of
a.push(new table1(5,1,2,3));
I would just have
a.push({id:5,x:1,y:2,z:3});
This may seem like a preferences question but it's a fundamental language question that I have as I try to understand how to model my app's data in JavaScript. Is there any advantage of the classes (with only data fields) or is it just a mistake. Thanks.
It depends,
Note: Most of the programmers coming from a strong OO language will have trouble like you in regard to JavaScript's functional behavior (you are not alone).
If you want to create something closer to C# I would do the following:
function Table1(id, x, y, z) {
this.id=id;
this.x=x;
this.y=y;
this.z=z;
}
Table1.prototype.mySpecialTable1Method= function()
{
console.log(this.id);
};
Implementation:
var t = new Table1(1, 2, 3, 4);
t.mySpecialTable1Method();// outputs: 1
If you need to have methods that interact with the (soon to be) objects then I would definitely go with the code above. In addition it will make it clear when working with the objects that are related to a specific 'type' (naming the data).
But if your objects do not require any special "treatment" then I don't see any problem to use normal js object literals and pass them along (probably good for small projects).
Something along the lines:
var table1 = {};
table1.id = 1;
table1.x = 2;
table1.y = 3;
table1.z = 4;
console.log(table1.id); //outputs: 1
Extra reference:
http://www.youtube.com/watch?v=PMfcsYzj-9M
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript
Update:
For the sake of readability and scalability and the point that you are coming from C# you may want to stick to the "class" implementation just because it will define the correlation between the raw data and the objects you are working with.
There is a good chance that you are going to work with some data that will probably be messy and unorganized.
MVC may be the solution for you. It tries to bring some order to the chaos that you are expecting. I recommend to check out some of them like: AngularJS or Ember.
Another solution may be reactive js - but mostly if you are going to interact with the DOM according to your data (ReactJS, and Facebook's React as some good ones).
As a note for security, I would like to add that mapping the data closely to the db isn't a best practice but its your call.
Javascript is a funny language, and there are plenty of ways to do things. An Object is an Object in Javascript with or without a name. {} is just a short-hand way to create one.
If you are going for readability, then your initial example would be the way to go.
If you just want to get the block of data into an array, then your second example is appropriate. Personally, I would use your later example if it is just data.
If you are using functions and what not as well as data storage, and plan on reusing it several times in your code, then yes, define your object and call it appropriately.
JavaScript has no classes, it is a functional language and a function is a first class citizen in js meaning that a function is an object.
From your example I can see that your intention for classes is simply to pass data and using json is perfect for this.
at the moment I'm writing a small app and came to the point, where I thought it would be clever to clone an object, instead of using a reference.
The reason I'm doing this is, because I'm collecting objects in a list. Later I will only work with this list, because it's part of a model. The reference isn't something I need and I want to avoid having references to outside objects in the list, because I don't want someone to build a construct, where the model can be changed from an inconsiderate place in their code. (The integrity of the information in the model is very important.)
Additional I thought I will get a better performance out of it, when I don't use references.
So my overall question still is: When should I prefer a clone over an reference in javascript?
Thanks!
If stability is important, then clone it. If testing shows that this is a bottleneck, consider changing it to a reference. I'd be very surprised if it is a bottleneck though, unless you have a very complicated object which is passed back and forth very frequently (and if you're doing that it's probably an indication of a bad design).
Also remember that you can only do so much to save other developers from their own stupidity. If they really want to break your API, they could just replace your functions with their own by copying the source or modifying it at runtime. If you document that the object must not be changed, a good developer (yes, there are some) will follow that rule.
For what it's worth, I've used both approaches in my own projects. For small structs which don't get passed around much, I've made copies for stability, and for larger data (e.g. 3D vertex data which may be passed around every frame), I don't copy.
Why not just make the objects stored in the list immutable? Instead of storing simple JSON-like objects you would store closures.
Say you have an object with two properties A and B. It looks like that:
myObj = {
"A" : "someValue",
"B" : "someOtherValue"
}
But then, as you said, anyone could alter the state of this object by simply overriding it's properties A or B. Instead of passing such objects in a list to the client, you could pass read-only data created from your actual objects.
First define a function that takes an ordinary object and returns a set of accessors to it:
var readOnlyObj = function(builder) {
return {
getA : function() { return builder.A; },
getB : function() { return builder.B; }
}
}
Then instead of your object myObj give the user readOnlyObj(myObj) so that they can access the properties by methods getA and getB.
This way you avoid the costs of cloning and provide a clear set of valid actions that a user can perform on your objects.
Due to performance and other issues, I want to split my code into seperate functions as before it was just one big ".ready" function.
I am new to javaScript/jquery but I thought I would give it a go myself. I have done exactly the way I thought it was done but my console is telling me things are undefined so I am guessing I have got things out of scope. I have read up on it in more detail, but still have not got anywhere.
My code works OK at the moment but I want to get into the habbit of clean coding. Can someone point out where I am going wrong so I can carry on myself?
Here is an example of what I have so far
//Global variables
var randomWord = [];
var listOfWords = [];
var populationNumber = [];
var attemptNumber = [];
var completionNumber = [];
var gridSize = [];
generateGrid();
startMusic();
randomizeReward();
//Click event to start the game
$(".start-btn-wrapper").click(function () {
startplay();
});
//Click event to restart the game
$(".restart-btn").click(function () {
restartplay();
});
Thanks
Fiddle: http://jsfiddle.net/QYaGP/
Fiddle with HTML: http://jsfiddle.net/QYaGP/1/
You need to start passing some information into the functions you're defining. If your functions all have no arguments, then you will have to use globally defined variables, hardcoded references to jquery selections etc in order to get anything done.
So as an example, you have a function
function replaySound() {
$("#hintSound").attr('src', listOfWords[randomWord].hintSound);
hintSound.play();
}
This is actually going to play the sound detailed in listOfWords[randomWord] via the element #hintSound. You could do that via:
function playSound(selector, wordlistEntry) {
$(selector).attr('src', wordlistEntry.hintSound);
$(selector)[0].play();
}
And then instead of calling replaySound(), you'd call:
playSound('#hintSound', listOfWords[randomWord]);
This way the behaviour that you want is wrapped up in the function, but the specifics, i.e. the data you need for it, are passed in via the arguments. That allows you to reuse the function to play any sound using any selector, not just #hintSound.
You'll find as you do that that you need to start choosing what a function will act on in the code that calls it, rather than in the function. That's good, because the context of what you're trying to achieve is there in the calling code, not in the function. This is known as 'separation of concerns'; you try to keep logic about a given thing confined to one area, rather than spreading it about in lots of functions. But you still want functions to allow you to encapsulate behaviour. This allows you to change behaviour cleanly and easily, without having to rewrite everything every time some part of the logic changes.
The result should be that you find several functions actually did the same thing, but with different specifics, so you can just have one function instead and reuse it. That is the Don't Repeat Yourself principle, which is also important.
If you are concerned about performance, I would look into using an framework such as AngularJS. You can inject modularized code. Even better, with MVC your view is bound to your model so by changing the model the view automatically updates itself.
Also, stop using class selectors. Use ID selectors. They are much faster. You also want to preload selectors (even with class selectors). That way you are only searching the DOM once:
var ele = $('#elementId');
$(ele).doSomething();
This way, you have a reference to the DOM element. You can use a datastructure to store all of your references outside of the global scope:
var elementReferences = {}; //declaration
elementReferences.mainPage = {}; //use
elementReferences.mainPage.root = $('#mainPage'); //load the root div of a page segment
elementReferences.mainPage.title = $(elementReferences.mainPage.root).children('#title'); //load the title
elementReference.mainPage.form = $(elementReferences.mainPage.root).children('#form'); //load the form
Now you can do this:
$(elementReference.mainPage.form).whatever();
and it doesn't have to search the DOM for the element. This is especially useful for larger apps.
If you put a function within document.ready, as per your fiddle, you are only able to access that function within the scope of the document.ready call. You really want to be able to load/unload functions as needed dynamically within the scope that they are required in, which is where angularjs comes into play.
You also, for the most part, want to remove your functions and variables from the global scope and put them into containers that are sorted by their dependencies and use. This is Object Oriented Programming 101. Instead of having a bunch of arrays sitting within the global scope where they could be overwritten by mistake by another developer, you want to put them within a container:
var arrays = {}; //create the object
arrays.whatever1 = [];
arrays.whatever2 = [];
Obviously, you will probably want a more descriptive name than "arrays". Functions work the same manner:
var ajax = {}; //ajax object
var ajax.get = function(){
};
var ajax.post = function(){
};
var ajax.delete = function(){
};
This generally promotes cleaner code that is more reusable and easier to maintain. You want to spend a good portion of your time writing a spec that fully documents the overall architecture before actually beginning development. NEVER jump the gun if you can help it. Spend time thoroughly researching and planning out the big picture and how everything fits together rather than trying to wing it and figure it out as you go. You spend less time having to reinvent the wheel when you do it this way.
It's developed by google, so it should be around for quite a while. I'm not sure if you are the guy in charge of your system's architecture, but if performance/reusability is an issue at your company it is definitely worth taking a look at. I'd be more than happy to give you a walkthrough regarding most of what I know in terms of software architecture and engineering. Just MSG me if you are interested. Always happy to help!
It's hard to get the exact specific information on OOP you're searching for.
I tried to keep it as short as possible:
I'm currently developing a jump n run in HTML5.
I have actually no real experience with developing games.
But I know how the basics are supposed to work.
I just want to know if I'm doing it right.
I have a game, player and level object.
What I'm currently doing is the following:
Game.player = new Player();
Game.level = new Level();
Game.level.load(Game.currentLevel);
...
Game.run();
Is that the best way or should I call them all on their own, e.g.:
var Player = new Player();
var Level = new Level();
Level.load(Game.currentLevel);
...
Game.run();
They way I'm doing it right now (the first one) seems more logic to me.
But.. in the level objects functions I have to check for various variables from the game object or call a function of its self. Thus I have to write Game.level.funcName inside the Level objects functions. But since Game.level doesnt actually exist at the level objects declaration point it feels kinda wrong and dirty. Here is another example:
Level.prototype.reset = function() {
this.load(Game.currentLevel);
};
The Game.currentLevel is hardcoded, isn't there any better way to detect which variable currently handles the game object, or is it totally ok the way I'm doing it ?
So the basic question is, whats the best way to let objects interact with each other ?
And one last question which is kinda offtopic, but what does ()(); do?
I sometimes see it beeing used like this:
(function() {
// Content
});
I hope you understand my concerns, thanks for your time and answers. :)
I would recommend the first approach, because it's more modular.
Your problem can be solved by simply passing a reference of the Game instance to the other components, so that they are aware of the game.
It's not uncommon for objects to have a cyclic structure in javascript:
Game.level = new Level();
Game.level._game = Game;
//...
Level.prototype.reset = function() {
this.load(this._game.currentLevel);
};
Of course that you can do it a bit more elegant by passing reference at initialization, but I think you got my point.
I think the way you're doing things look pretty good. About the last part of your question, that's called an immediate function. It's a function that's called right after it's declared. You can see more info about here: http://javascriptmountain.com/2011/06/functions/immediate-functions-in-javascript-the-basics/
I have answer to last question
Question: what does ()(); do? I sometimes see it beeing used like this:
(function() {
// Content
});
It is the self executing closure. I will provide simplest explanation here. When we write java script function they need to be called to execute them.
For example,
function alertMe(){
alert('alerted');
}
alertMe(); // We need to call intentionally for execution of function.
Self executing closure doesn't require calling separately.
For example,
(function(){
alert('alerted');
})();
Above javascript executes automatically, when script is loaded. Same Question is answered on SO here.
Start with the user interaction and work backwards. It's possible to get too much involved in the design process and come up with convoluted designs if that design is too flexible or is solving too many problems.
Based on my limited knowledge of games, and even lesser of game programming, and what you've shown us, I believe there are two user interactions that you're dealing with here.
User picks a particular game level to play
User resets that game level
Storing the current level as a property of the game object is perfectly fine. I can think of two methods that would be needed to handle these interactions both of which would make sense on a Game object.
function setLevel(levelNumber) {
this.currentLevelNumber = levelNumber;
this.level = new Level(levelNumber);
}
function resetCurrentLevel() {
this.setLevel(this.currentLevelNumber);
}
I would break the connection from a Level object to the Game object, and load a level independently of the game as much as possible. So instead of doing,
game.level = new Level();
game.level.load(game.currentLevel);
I'd push the burden of initializing a level upon the Level constructor itself as in,
game.level = new Level(8);
or even better, make it a method call on the Game object as in my example above - setLevel(n). The method will be responsible for ensuring that the game object is consistent when the level changes.
game.setLevel(8);
Since the reset function resetCurrentLevel internally uses this method, handling of level changes will be unified whether it's loading a new level, or resetting a current level.