Help me organize my stipid javascript
-
I'm working on a webapp that uses Knockout (which I really really like!), but I'm having some trouble with my "working knowledge" of JavaScript.
I built my ViewModel following the Knockout tutorials, and it works the way I expect. But I ended up writing a bunch of methods like
loadClientByDay
,loadClientByName
, etc. Also, because it's Knockout, I have a bunch of observables, likecurrentClient
, etc.I'd like to change the method names to be more like
app.load.client.day
,app.load.client.name
, etc. That should be straight-forward enough. But how do I actually do it? As much as possible, I'd like to keep using the notation:function ViewModel() { var self = this; self.app.state.client = ko.observable(); self.app.load.client = function () { loadStuff }; }
The naive thing, to just initialize the fields I will use, didn't work. It keeps complaining that, for example,
app.state
isn't defined. So I tried using empty objects and I got kind of stuck. I could keep plugging along with initializing a ton of empty objects, but is there a better way?
-
You can use nested object literals:
self.app = { load: { client: { day: function (day) { /**/ }, name: function(name) { /**/ } } } };
Notice the similarity to JSON (or the other way around, really).
Also, starting with ES2015 (I think) there's an alternate, shorter way of writing methods:
self.app = { load: { client: { day(day) { /**/ }, name(name) { /**/ } } } };
-
@zecc Yeah, I've beed doing the first style a bit:
self.app = { state: {} , load: {} , resource: {} }
And then filling in the components with
self.app.state.client = ko.observable()
and so on.
I guess, thinking about it, what I REALLY want is more like modules or namespaces than objects. One of the things that has me stuck is where a method like
loadSheetsForClient
should if into the scheme. Should it beapp.load.sheets.client
orapp.load.client.sheets
. And, if it's the latter, how do I make it play nice with the fact that I already have anapp.load.client
method? (I'm leaning toward theapp.load.sheets.*
style)
-
@zecc There's also the arrow notation:
day: (foo) => { /**/ }
Though that one is best used if you don't want to change
this
to the context of the function thus created. No morethat = this
-
@rhywden Only works in later versions of JS and if you aren't using a transpiler like babel ... it won't work on anything except for Chrome.
-
@captain said in Help me organize my stipid javascript:
app.load.client.sheets
. And, if it's the latter, how do I make it play nice with the fact that I already have anapp.load.client
method? (I'm leaning toward theapp.load.sheets.*
style)Since JavaScript is magical and full of wonder, it is perfectly acceptable* to add members to functions. E.g. (from console):
> var helloFn = () => console.log('hello world'); undefined > helloFn.houseOnFire = () => console.log('this is fine') () => console.log('this is fine') > helloFn() VM30513:1 hello world undefined > helloFn.houseOnFire() VM30527:1 this is fine undefined
*
-
And a better explanation (Mozilla's explanations suffer from some of the MSDN docs of the past, a very vague and unrealistic example).
Here is a better example of how to use the bind().
You can rebind "this" since IE9 I believe (I am not sure tbh). There is also a polyfill for older browsers.
-
@captain you can do this using something like this:
function namespace(object, path) { if (typeof path === 'string') path = path.split('.'); return path.reduce((obj, element) => element in obj ? obj[element] : (obj[element] = {}), object); } function ViewModel() { var self = this; namespace(self, 'app.state').client = ko.observable(); namespace(self, 'app.load').client = function () { loadStuff }; }
-
@captain said in Help me organize my stipid javascript:
One of the things that has me stuck is where a method like loadSheetsForClient should if into the scheme. Should it be app.load.sheets.client or app.load.client.sheets. And, if it's the latter, how do I make it play nice with the fact that I already have an app.load.client method? (I'm leaning toward the app.load.sheets.* style)
You could assign the object to them all, but there lies madness.
@lucas1 said in Help me organize my stipid javascript:
@rhywden Only works in later versions of JS and if you aren't using a transpiler like babel ... it won't work on anything except for Chrome.
Lies!
Oh, FFS, it doesn't embed. Here:
-
@zecc said in Help me organize my stipid javascript:
Lies!
Well, TBF you're only half wrong, if we consider relative browser usage.
-
@zecc IE 11 isn't an unusual platform, especially if you have corp clients.
I am a mobile js dev mostly these days, but at least I bother to check on older desktop browsers.
If I want to make sure my arrow syntax works, I make sure I put it through the compiler.