Having troubles implement my app in an Object Oriented manner - javascript

I've been coding JS for a while, but I've never did anything object oriented. I usually just defined all my variables at the top, and then just used them all. I kept hearing over and over to use OO, but now I can't do what I want and I can't get any help.
Here is a fiddle, along with semi identical code:
http://jsfiddle.net/zDeAJ/1/
var App = {
options: {
/* ------------------------------------
Options (PREFERABLY DONT CHANGE)
--------------------------------------- */
baseDomain : 'google.com',
apiVersion : '/api/v1'
},
state: {
current: App.options.baseDomain + App.options.apiVersion
}
}
So doing App.options.baseDomain (or this.options.baseDomain) won't work for me. What's the usefulness of defining Application level variables if I can't define other application level values based on them? I know this is a vague question but I really don't know what I'm asking... I just have a problem in that what I was easily able to accomplish with just a bunch of variables that held not only settings, but state within my application, is not so easy with my knowledge of Javascript OO patterns....
​
Edit: Alright, this is specifically what I want to do:
http://i.imgur.com/ak5YD.png
But I wasn't aware of the limitations... so I need a way around it, which sticks as close and elegant as possible to this implementation.

You can think of your approach as creating an "Instance" object called App.
Here's a slightly different approach.
function App () {
// Save a reference to the object
var that = this;
that.options = {
baseDomain: "google.com",
apiVersion: "/api/v1"
};
that.state = {
current: that.options.baseDomain + that.options.apiVersion
};
}
var myApp = new App();
// Write the current state to the screen
document.write(myApp.state.current);
Here's the JSFiddle: http://jsfiddle.net/zDeAJ/1/
Hope this helps!

Your question is quite generic; you should be more specific about what you're trying to accomplish.
That aside, read the documentation on objects;
Taken from w3schools:
With JavaScript you can define and create your own objects.
There are 2 different ways to create a new object:
1. Define and create a direct instance of an object.
2. Use a function to define an object, then create new object instances.
Way 1:
personObj=new Object();
personObj.firstname="John";
personObj.lastname="Doe";
personObj.age=50;
personObj.eyecolor="blue";
Way 2:
function person(firstname,lastname,age,eyecolor)
{
this.firstname=firstname;
this.lastname=lastname;
this.age=age;
this.eyecolor=eyecolor;
this.changeName=changeName;
function changeName(name) {
this.lastname=name;
}
}

Not one of you answered my question.... I thought about it a little... I could use a named function inside of the literal to access it... and if I wanted (not necessary) I could even assign it back to the options object
http://jsfiddle.net/zDeAJ/9/
var App = {
options: {
/* ------------------------------------
Options (PREFERABLY DONT CHANGE)
--------------------------------------- */
baseDomain : 'google.com',
apiVersion : '/api/v1',
blah: ''
},
state: function(){
this.options.blah = this.options.baseDomain + this.options.apiVersion;
}
}
App.state();
console.log(App.options.blah);
​

JavaScript is an interpreted language. That means your code is evaluated from the inside out or the most inner expression is evaluated and passed to the next outer expression.
In your example the value of options get's evaluated first and next the value of state. The problem is that you can't access the associative array of App before it is fully evaluated, wich is not the case during the evaluation of the value of state.
EDITED
Sorry for not answering correctly. Here is a refined approach from your second:
var App = {
options: {
/* ------------------------------------
Options (PREFERABLY DONT CHANGE)
--------------------------------------- */
baseDomain : 'google.com',
apiVersion : '/api/v1',
blah: ''
},
blah: function(){
return App.options.baseDomain + App.options.apiVersion;
}
}
console.log(App.blah());

You could do the following (in JavaScript, functions are objects):
function App () {
// Save a reference to the object
this.options = {
baseDomain: "google.com",
apiVersion: "/api/v1"
};
this.state = {
current: this.options.baseDomain + this.options.apiVersion
};
}
var myApp = new App();
console.log(myApp);

Related

Truly protecting data members (of classes/IIFE variables) in JavaScript

Context
I have been tasked with fixing a big bug on the menu-edit page, which was caused by a stale element issue, caused by the HTML elements for it being rendered server-side. In my three-day fight against this bug, I got some inspiration from Angular and decided to try to make a menu state that will power everything on the page (adding/removing categories/items, and later, pagination of the modals for the adding)
Some Code
I came up with this IIFE (to be the "controller" of the MVC. Selector modals hit the add methods of this, and delete buttons hit the remove methods of this. Also, this gets passed to template-render function, which is literally the first thing hit when a modal gets popped):
/* all the categories, items, and modifiers that power this page */
var menuState = (function() {
let _categories = {
attached: [],
available: []
}, _items = {
attached: [],
available: []
}, _modifiers = {
attached: [],
available: []
}
function getExposedMethodsFor(obj) {
return {
all : function() { return obj.attached.concat(obj.available) },
attached : function() { return obj.attached },
available : function() { return obj.available }
// ... other methods that work on obj.attached,obj.available
}
}
let categoryExposedMethods = getExposedMethodsFor(_categories)
// other exposer objects
return {
getAllCategories : categoryExposedMethods.all,
getAttachedCategories : categoryExposedMethods.attached,
getAvailableCategories : categoryExposedMethods.available
// the rest of the exposed methods irrelevant to this question at hand
}
})()
OK, so what's the problem?
The problem is that this is false sense of security, it seems. When I try to XSS-test this structure alone, it fails.
I test it with three entities in _categories, all of which are attached, causing
menuState.getAllCategories().length
to return 3 and
menuState.getAvailableCategories().length
to return 0. Good news is that when I tried
menuState.getAllCategories().push('a')
menuState.getAllCategories().length
I still get three.
However, when I go
menuState.getAvailableCategories().push('b')
menuState.getAvailableCategories().length
I get 1, instead of 0 !!
Is there truly a way to lock down the other getters here?! If not, what are my alternatives?
I fixed it with Object.freeze, which I already used for refactoring the "enums" the dev before me wrote when he was working on this project. What it does is fully protect a state from any type of changes, including:
adding properties
deleting properties
modifying properties
re-assigning the object/array being "frozen"
How I use it
In the helper method, I did the following :
attached : function() { return Object.freeze(obj.attached) },
available : function() { return Object.freeze(obj.available) },
This prevents the arrays being changed from those methods, thus shutting down this type of XSS. Also, menuState was declared with const.

How to apply many different rules on an object efficiently and using object oriented techniques using javascript

This is my first pass at this task i have. I need to update my UI based on the field. The field can be of different types. Here I am just checking for a memo or boolean type.
// UI Field Rule set.
var UIFieldRules = {
isMemo: function() {
return this.DataType === DataTypeKVP("Memo");
},
isBoolean: function() {
return this.DataType === DataTypeKVP("Boolean");
},
MapToList: function() {
if (UIFieldRules.isMemo.call(this) || UIFieldRules.isBoolean.call(this)) {
console.log("memo or bool");
console.log(UIFieldRules.isMemo.call(this));
console.log(this);
MAPTOLIST_SELECTOR.prop('disabled', true);
return;
} else {
MAPTOLIST_SELECTOR.prop('disabled', false);
console.log("UI field rules found memo");
}
}
};
I then call this object upon loading all the fields.
UIFieldRules.MapToList.call(field);
This works fine and satisfied the task, but now i need to apply more rules to the fields. (stop me if you heard this one before)
How can I get this set where i can just add a rule to a collection and have them all applied dynamically in javascript?
Update provide example:
function MapToList(field){
isBoolean:function(){}
isMemo : function(){}
execute : function(){
if (UIFieldRules.isMemo.call(this) || UIFieldRules.isBoolean.call(this)) {
console.log("memo or bool");
console.log(UIFieldRules.isMemo.call(this));
console.log(this);
MAPTOLIST_SELECTOR.prop('disabled', true);
return;
} else {
MAPTOLIST_SELECTOR.prop('disabled', false);
console.log("UI field rules found memo");
}
}
}
Then if i want to create more rules (which I do) should I create another object like the one above? Is there a best practice way of doing this in JS?
var rules = [];
rules.push(new MapToList(field));
rules.push(new RegExEnabled(field));
$.each(rules,function(item){
item.execute();
});
Your example approach is exactly fine. Create multiple objects that all implement the same interface, put them in a list, and then call a common method on each of them:
var rules = [MapToList, RegExEnabled];
rules.forEach(function(item){
item.execute(field);
});
However, you might want to notice that you typically you don't need a constructor + new if your object is not stateful or does not have any parameterisation, a simple object literal is enough.
And similarly, if your shared interface boils down to a single execute method, what you actually want is not a list of objects but just a list of functions you can call. It's not Java :-)

What is a proper way to create argument var names in a module for a new Class creation?

In the following code example I want to somehow create a var myThingName via a functions arguments so I can avoid having to build global var names outside of the Module.
I have tinkered with window['myvarname'] = "yada"; But that's a global and feels like a complete hack.
In short, I am assuming I need to have a way to make many vars like : myThingName_1 myThingName_2 etc...
Background: I am trying to build a Canvas Element constructor to put any number of individual Canvas elements onto the screen. I am using various libraries like Paper.js Kinetic.js etc. When trying to streamline the production I built a Module wrapper but am now stuck at how to create unique var names for the libraries KLASS constructor for their various implementations of stage or scope.
Perhaps I am doing things totally incorrectly from the start.
But at the moment I am stumped as to how this goes about or what the name of the pattern I am looking.
var MagicThingModule = {
createThing : function(myThingNameAsString){
var myThingName = myThingNameAsString;
myThingName = new KLASS.Shape({ // code });
},
init : function(myThingNameAsString){
createThing(myThingNameAsString);
}
}
MagicThingModule.init("sendNameForThing_1");
How about:
var MagicThingModule = {
allMyThings: {},
createThing : function(myThingNameAsString){
var myThingName = myThingNameAsString;
myThingName = new KLASS.Shape({ // code });
this.allMyThings[myThingNameAsString] = myThingName;
},
// use me to et your thing back...
getMyThing: function(myThingName){
return this.allMyThings[myThingName];
},
init : function(myThingNameAsString){
createThing(myThingNameAsString);
}
}
and you can later reference it by:
var myThing = MagicThingModule.getMyThing("sendNameForThing_1");

Javascript Module Pattern Memory Footprint and Performance

I am using the Javascript Module Pattern to try and implement C# enumeration-like functionality. I have two ways that I am currently thinking about implementing this functionality but I do not understand all the benefits or advantages of one way versus the other.
Here is implementation 1:
var MyApp = (function (app) {
// Private Variable
var enums = {
ActionStatus: {
New: 1,
Open: 2,
Closed: 3
}
};
// Public Method
app.getEnum = function (path) {
var value = enums;
var properties = path.split('.');
for (var i = 0, len = properties.length; i < len; ++i) {
value = value[properties[i]];
}
return value;
};
return app;
})(MyApp || {});
// Example usage
var status = MyApp.getEnum("ActionStatus.Open");
And now implementation 2:
var MyApp = (function (app) {
// Public Property
app.Enums = {
ActionStatus: {
New: 1,
Open: 2,
Closed: 3
}
};
return app;
})(MyApp || {});
// Example usage
var status = MyApp.Enums.ActionStatus.Open;
The main difference is in using a "private" variable vs a "public" property to store the enums. I would think implementation 1 is a little slower but I was not sure if keeping the enums as "private" reduced the memory usage. Can anyone explain the difference in memory footprint and performance for the two (if any)? Any other suggestions/advice are appreciated.
...but I was not sure if keeping the enums as "private" reduced the memory usage
The opposite, if anything: You still have to have the enums object, and you have to have a function to access it.
In terms of speed, I wouldn't worry about it. The added function call won't make any real difference (I looked into it when worried about using the new forEach and such, and even on IE6 with its massively slow JS engine, it just doesn't matter).
In a couple of years, you'll probably be able to have the best of both worlds: Enums that are read-only, thanks to ECMAScript5's Object.defineProperties feature:
var Enums = Object.defineProperties({}, {
ActionStatus: {
value: Object.defineProperties({}, {
New: {value: 1},
Open: {value: 2},
Closed: {value: 3}
})
}
});
// Usage
var n = Enums.ActionStatus.New; // 1
By default, properties created with defineProperties are read-only.
In fact, you can basically have that now if you add an ES5 "shim" to create Object.defineProperties on browsers that don't yet have it natively. The "shimmed" version would create read-write properties, since only the natively-supported version can really create read-only properties, but you can write the code now and know that it will work as you like on modern browsers (about half of all web surfers currently have them) while still working, just with less robustness, on less-modern ones.
And of course, EMCAScript6 may take things further, but that's still a future thing.

Advice needed... Javascript OOP/namespacing

right now i am at a point where i feel that i need to improve my javascript skills because i already see that what i want to realize will get quite complex. I've iterrated over the same fragment of code now 4 times and i am still not sure if it's the best way.
The task:
A user of a webpage can add different forms to a webpage which i call modules. Each form provides different user inputs and needs to be handled differently. Forms/Modules of the same type can be added to the list of forms as the user likes.
My current solution:
To make the code more readable and seperate functions i use namespaced objects. The first object holds general tasks and refers to the individual forms via a map which holds several arrays where each contains the id of a form and the reference to the object which holds all the functions which need to be performed especially for that kind of form.
The structure looks more or less similar to this:
var module_handler = {
_map : [], /* Map {reference_to_obj, id} */
init: function(){
var module = example_module; /* Predefined for this example */
this.create(module);
},
create: function(module) {
//Store reference to obj id in map
this._map.push([module,id = this.createID()]);
module.create(id);
},
createID: function(id) {
//Recursive function to find an available id
},
remove: function(id) {
//Remove from map
var idx = this._map.indexOf(id);
if(idx!=-1) this._map.splice(idx, 1);
//Remove from DOM
$('#'+id+'').remove();
}
}
var example_module = {
create: function(id) {
//Insert html
$('#'+id+' > .module_edit_inner').replaceWith("<some html>");
}
}
Now comes my question ;-)
Is the idea with the map needed?
I mean: Isn't there something more elegant like:
var moduleXYZ = new example_module(id)
which copies the object and refers only to that form.... Something more logical and making speed improvements?? The main issue is that right now i need to traverse the DOM each time if i call for example "example_module.create() or later on any other function. With this structure i cant refer to the form like with something like "this"???
Do you see any improvements at this point??? This would help me very much!!! Really i am just scared to go the wrong way now looking at all the stuff i will put on top of this ;-)
Thank You!
I think you're looking for prototype:
=========
function exampleModule(id)
{
this.id = id;
}
exampleModule.prototype.create = function()
{
}
=========
var module1 = new exampleModule(123);
module1.create();
var module2 = new exampleModule(456);
module2.create();

Categories