I'm currently making a tiny game structured like so:
let Game = function() {
let privateVar;
// private would be an example private variable assigned later
// Other private variables go here
return {
Engine: function() {
// More specific private variables
init: function() {
privateVar = this.sampleValue;
// Game.Engine.sampleValue doesn't help either
// Start up everything, for example, calling a Graphics method:
Game.Graphics.method1();
},
sampleValue: 10,
// Other methods
}
Graphics: Graphics()
}
}
function Graphics() {
// Visuals-specific private variables
return {
method1: function() {
console.log(privateVar);
// This would complain about the variable not being defined
}
// methods
}
}
Game.Engine.Init();
The idea is to separate the visual code from the internal code by calling the Graphics() function in the Graphics method (so I can for example build the Graphics() function in a separate file for example). However, when I do this, the Graphics method loses the private variable I declared at the beginning and assigned at the init method, and spits out Uncaught ReferenceError: private is not defined whenever it's called by some method in Graphics.
I guess one solution would be just reassigning those privates in Graphics(), but that would somewhat kill the purpose. Anyone has a better idea? Thanks in advance.
EDIT: Made the code a bit easier to understand what I'm getting at
If you want private variables your Graphics type should not access them. How about declaring public variables instead ?
Like this for instance:
let Game = function() {
this.publicVar = "value";
}
Or you can declare getters to access private fields and pass Game instance to the Graphics type. Like this :
let Game = function() {
let privateVar = "value";
this.getPrivateVar = function() {
return privateVar;
}
}
function Graphics(game) {
// ...
}
I think that you are trying to use O.O. in javascript.
Javascript is prototyped, so, the way you will use O.O. is different than usual languages. see mozilla reference
I think you should create js classes like these:
/**
* #class Game Class
*/
function Game() {
this.privateProperty;
this.engine = new Engine(); //engine object of this game
this.graphics = new Graphics(); //graphics object of this game
}
Game.prototype.oneGameMethod = function(){
};
/**
* #class Engine Class
*/
function Engine(){
this.privateProperty;
}
Engine.prototype.oneEngineMethod = function(){
};
/**
* #class Graphics class
*/
function Graphics() {
// Visuals-specific private variables
this.visualProperty;
}
Graphics.prototype.oneMethodExample = function(){
};
Than you can create an Game object and call its methods and so on:
var myGame = new Game();
Related
I'm struggling with my JS code structure that's becoming apparent during my unit testing attempts. I'm used to the class structure, but I'm a bit lost in the JS world where there aren't any classes. I'm looking for a way to organize my code in the traditional class/constructor architecture. Here's what I have:
function ddGridSelector(primaryId, templateDefault, gridObj) {
//set the variables
this.primaryId = primaryId,
this.defaultTemplate = templateDefault,
this.gridObj = gridObj,
this.gridObj.searchVal = '',
this.init = ddgs_init
}
function ddgs_init(ddgs_obj) {
ddgs_setDefaultTemplate(ddgs_obj);
ddgs_initGrid(ddgs_obj);
ddgs_initKendoWindow(ddgs_obj);
ddgs_initKendoButton(ddgs_obj);
ddgs_initResetButton(ddgs_obj);
ddgs_addGridEventListener(ddgs_obj);
}
function ddgs_setDefaultTemplate(ddgs_obj) {
//doing stuff
}
function ddgs_initGrid(ddgs_obj) {
//more stuff
}
To call any of these...
var ddGridSelector_new = new ddGridSelector('PrimaryIdentifier', templateDefault, gridObj);
ddGridSelector_new.init(ddGridSelector_new);
It seems really redundant to pass my object to my function that's specified in my constructor so I'm sure I'm missing something obvious here. Really would appreciate some guidance on the matter. I think I'm close to being on a good path.
ES5 Way
You can do "functional classes" like this, which are pretty self explainable:
function User(name) {
// name is thus "private" here because it's
// not put under "this.name"
this.sayHi = function() {
alert(name);
};
}
let user = new User("John");
user.sayHi(); // John
There's also the prototype class pattern as well:
function User(name, birthday) {
this._name = name;
}
User.prototype.sayHi = function() {
alert(this._name);
};
let user = new User("John");
user.sayHi(); // John
Source/Tutorial with the examples listed here
ES6+ Way
In ES6 you can declare classes in a way that looks more like traditional programming languages:
class User {
constructor(name) {
this.name = name;
}
sayHi() {
alert(this.name);
}
}
let user = new User("John");
user.sayHi(); // John
However you will need a transplier like Babel or Typescript to compile it down to web compatible code if you are targeting platforms such as IE (all versions), Opera Mini, and the Android Browser (4.4.x, ~16% of all Android versions in the field) (web compat sources), or things such as Cordova on older iOS devices (< 10, UIWebView, etc).
Node.js should have support for classes from 4.8.4(!) and above, surprisingly enough (source).
but I'm a bit lost in the JS world where there aren't any classes.
But... there are!
class ddGridSelector {
constructor(primaryId, templateDefault, gridObj) {
//set the variables
this.primaryId = primaryId,
this.defaultTemplate = templateDefault,
this.gridObj = gridObj,
this.gridObj.searchVal = '',
}
init() {
this.setDefaultTemplate();
this.initGrid();
this.initKendoWindow();
this.initKendoButton();
this.initResetButton();
this.addGridEventListener();
}
setDefaultTemplate() {
//doing stuff
}
initGrid() {
//more stuff
}
}
I tend to love this structure for a class-like layout when I want to avoid new features. It gives you a private scope where you can scope functions and shared variables as you need them and lets you separate out a "constructor" and public methods on the prototype.
var MyType = (function () {
function MyType() {
//My Constructor
}
MyType.prototype = {
constructor: MyType,
publicMethod: privateMethod
};
function privateMethod() {
...
}
return MyType;
}());
The outer scope runs immediately and keeps the global namespace clean. We augment the private function with prototype instance methods, define any "private" methods needed, and return the private type after setup. This lets you instantiate a class like normal and call any methods.
var example = new MyType();
example.publicMethod();
I'm building a library that is a loading screen which allows me to call Loader.Show(), Loader.Hide() or Loader.Step() from various different documents.
I've built the library, however I do not fully understand the various ways to declare objects. Whats the difference in the following two models, and which is better?
//Example 1
var Robot = (function () {
var metal = "Steel";
return {
killAllHumans: function() {
alert(metal);
}
}
})();
Robot.killAllHumans();
//Example 2
var NonRobot = {
runState: "Normal",
run: function() {
alert(this.runState);
}
}
NonRobot.run();
I understand that both example 1 & create objects. I also understand that in Example 1, metal is a private variable. I do not know how to create a private variable in example 2. Is the only difference the scope?
This method creates a private context where you could add your own variable and do some intermediate evalations or even create private variables, such as metal
var Robot = (function () {
var metal = "Steel";
return {
killAllHumans: function() {
alert(metal);
}
}
})();
On the other hand, this version creates is an object literal:
var NonRobot = {
runState: "Normal",
run: function() {
alert(this.runState);
}
}
NonRobot.run();
runState is not a private property of NonRobot and it can be manipulated by outside forces.
In the first instance you are using an Immediately Invoked Function Expression as a constructor.
In the second, you are creating an object using an object literal.
I've been writing an application and I have had a lot of success breaking different pieces of functionality into the so called "Module" pattern where you have a self-executing singleton with public and private members.
var WidgetModule = (function($, options) {
// Private variable
var someVar;
// Private functions
function somePrivateFunction() {
}
// Define the public members
var self = {
init: function() {
},
someFunction: function() {
}
};
return self;
})(jQuery, options);
I have now run into a case where I have several modules which I would like to be able to create multiple instances of.
I know this pattern is based on the singleton but I wonder if there was a painless way to modify this pattern to support creating instances of them?
When I need common functionality for multiple objects, here's the pattern I usually use (adjusted to account for the code you presented):
var Widget = (function($) {
var pubs = Widget.prototype;
// Private variable -- global to all instances
var someVar;
// The constructor
function Widget(options) {
var privateInstanceVar;
this.privateInstanceFunc = function() {
return privateInstanceVar;
};
}
// Private functions -- global to all instances
function somePrivateFunction() {
}
// Define the public members
pubs.init = function() {
};
pubs.someFunction = function() {
};
return Widget;
})(jQuery);
Usage:
var w = new Widget({someOption: "here"});
As you can see, you can share private data amongst all instances created by the constructor, and if you really want to, you can have private data that's shared only with certain select instance functions. Those functions have to be created in the constructor, which has reuse implications, whereas functions that don't need the truly-private instance data can be on the prototype and therefore be shared by all instances.
Better yet, since you already have a handy scoping function, you can help your tools help you by giving your public functions actual names:
pubs.init = Widget_init;
function Widget_init() {
}
I mostly don't actually code the above, because I've defined a helper factory that makes it a bit more concise (and makes it easier to do specializations of functionality, like a Car inheriting functionality from Vehicle); details here.
What about this:
function WidgetModule(options){
//var $ = jQuery;
// Private variable
var someVar;
// Private functions
function somePrivateFunction() {
}
// Define the public members
var self = {
init: function() {
console.log(options.id);
},
someFunction: function() {
}
};
return self;
}
var w1 = WidgetModule({id:1}),
w2 = WidgetModule({id:2});
w1.init(); // --> 1
w2.init(); // --> 2
If I create a constructor function BlahWidget and give it 2 public methods: publicHello and secondHello. I assign publicHello directly inside the widget using 'this' but use the prototype object to assign the secondHello method, what difference does that really make to the behaviour of the 2 methods on the widget?
var BlahWidget = function(){
this.publicHello = function(){
alert("Hello");
}
};
BlahWidget.prototype.secondHello = function(){
alert("Second Hello");
}
My understanding was that using .prototype allows it to be called by inherited objects. But turns out that this is not the case. Both methods can be called by the inherited function objects, as shown below:
var MiniBlah = function(){
this.callSupers = function(){
this.publicHello();
this.secondHello();
}
}
MiniBlah.prototype = new BlahWidget();
MiniBlah.prototype.constructor = MiniBlah;
var x = new MiniBlah();
x.callSupers();//calls both publicHello and secondHello
The difference is that functions declared on the prototype object are shared across instances of objects created by a constructor function whereas functions declared inside of the body of a constructor function are not, they belong to the object constructed from the function.
What this means in practice is that you could create a load of objects from a constructor function with a function on the prototype doing X, then change that function on the prototype to do Y and all object instances will get the new functionality of the function.
An example
var BlahWidget = function(){
this.publicHello = function(){
console.log("Hello");
}
};
BlahWidget.prototype.secondHello = function(){
console.log("Second Hello");
}
var blah1 = new BlahWidget();
var blah2 = new BlahWidget();
blah2.publicHello = function() {
console.log("Goodbye");
}
blah1.secondHello(); // logs SecondHello
blah2.secondHello(); // logs SecondHello
BlahWidget.prototype.secondHello = function(){
console.log("Second Goodbye");
}
blah1.secondHello(); // logs Second Goodbye
blah2.secondHello(); // logs Second Goodbye
blah1.publicHello(); // logs Hello
blah2.publicHello(); // logs Goodbye
Every single instance of "BlahWidget" will have its own distinct copy of the "publicHello" function.
Also, though this is just academic, I'm not sure I'd say that "prototype" is a keyword; it's more like a "special property name".
In JavaScript Functions are so powerful to build OOPs and modular concepts. Following concepts are implemented using Function only in JavaScript:
Method
Class
Constructor
Module
Below code shows the code which create class MyClass and it has private members:
function MyClass(a) {
var count = 3; // private member
// this check function is private function
function check() {
if (count > 0) {
count--;
return true;
}
else {
return false;
}
}
this._a = a;
this.get = function () {
if (check()) { // use of private function
return this._a;
}
else {
return "Thullu"; // after invoking get method 3 times in the object this else will be executed
}
}
}
In the above code variable, count is private as any object created from MyClass will not have this variable similarly function check() is private function as this function is not part of this in the MyClass. When we create an object of MyClass using new keyword this is returned. This concept is possible in JavaScript because of lexical scoping (functional scoping).
When we create object of this class MyClass, and call the get method more than 3 times:
I would like to write few points regarding new keyword.
When a function is called with the new operator, a new object is created with prototype members and assigned to this.
Above statement is true only if there is no explicit return value in the function. If explicit return is present in Class (function), then same return will be assigned to the object.
I would like to give here one more example with very basic functionality like in all OOP languages we have. We declare private field and then use public properties to expose the private field, in more formal and OOPs way we create Get and Set method to update private field or retrieve private member of class.
Same get and set functionality for private variables in JavaScript we can achieve as shown in below example:
// private class with get and set methods
function MyClass() {
var _privateField = 0; // It is private field as it is not part of "this"
this.GetPrivateField = function () {
return _privateField;
};
this.SetPrivateField = function (value) {
_privateField = value;
};
}
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.