Can I use AngularJS to handle and load my objects - javascript

I've got some CoffeeScript classes which I use and extend in my code. How can I use angularjs to not have to create the usual module cruft like
MyNamespace = MyNamespace || {}
MyNamespace.SuperClass = class
and in a different file
MyNamespace = MyNamespace || {}
class ChildClass extends MyNamespace.SuperClass
MyNamespace.ChildClass = ChildClass
Could I simply write
angular('MyModule').factory, 'SuperClass', () ->
class SuperClass
constructor: (#id) ->
return SuperClass
and extend from that class via
angular('MyModule').factory, 'ChildClass', ['SuperClass', (SuperClass) ->
class ChildClass extends SuperClass
constructor: (id) ->
super(id)
return ChildClass
]
My problem is actually that Im using CoffeeScript to compile all objects into a single file. Now if a childclass is above the baseclass, the baseclass will be undefined and I'll get an error. I'm looking for an elegant and easy way how to solve this.

If you use Angular's DI system, it should ensure that your classes are instantiated in the correct order, regardless of which is loaded first. Is there actually an issue with your example?

With Angular you can do away with putting your classes in namespaces, since the name of your module / service can be qualified and effectively serve the same purpose.
What I don't think Angular will help with is ensuring that your super class code is run before your child class code. For that there seems to be about 8000 ways of solving the problem and none of them standard - requireJs, coffeetoaster, brunch, grunt, cake.....
I use grunt, and specify the order in which I want to concat my coffeescript.

Related

ES6 Parent class overrides child prototype

I decided to write ES6 class for Express server, but extended Express overrides child prototype, and there is no way to use methods and props that defined outside constructor. See code:
import Express from 'express'
export default class Server extends Express {
constructor(options) {
super(options.expressOptions || {})
super.use(cookieParser()) // TypeError: (intermediate value).use is not a function
this.use(bodyParser.json()) // This definition works cause of overridden prototype
this.use(Express.static('static'))
this.test() // TypeError: this.test is not a function
this.test1 = '123' // Contains in Server final prototype
}
test() {
console.log('test')
}
}
And problem with super class definition. I don't know how to save child prototype. It's will be very precious if you help.
Having looked again at this, I see the problem.
express is not a constructor.
You are treating express as if it were a constructor that you call using new Express. This is not how it works: you just call it with, for example, const app = express(). In fact, express is a function (here's the source code) that creates the object for you, in an old-fashioned (non-ES6) way.
As far as I am aware, it is not possible to subclass any of the core Express objects. You could, I guess, use classes to wrap the Express framework objects, but that doesn't seem intuitive to me.

ES6 modules: Export single class of static methods OR multiple individual methods

I'm using ECMAScript6 modules. What is the correct way to export/import multiple methods from a module from the options below?
Single class of static methods:
//------ myClass.js ------
export default class myClass {
static myMethod1() {
console.log('foo');
}
static myMethod2(args...) {
console.log('bar');
}
}
//------ app.js ------
import myClass from 'myClass';
myClass.myMethod1(); //foo
Multiple exported methods:
//------ myMethods.js ------
export function myMethod1() {
console.log('foo');
}
export function myMethod2() {
console.log('bar');
}
//------ app.js ------
import {myMethod1, myMethod2} from 'myMethods';
myMethod1() //foo;
//OR
import * as myMethods from 'myMethods';
myMethods.myMethod1() //foo;
1) Exporting:
A class of just static methods feels like a bit of a 'code smell' but similarly exporting everything individually does feel a bit verbose. Is it simply developer preference or are there performance implications here?
2) Importing:
'* as' syntax is my preferred method as it allows you to use the dot notation (referencing both the module AND the method) aiding code readability. Does this have performance implications though when I may only be using 1 of the methods?
A class of just static methods feels like a bit of a 'code smell'
Yes indeed. You don't need a class structure here! Just export a normal "module" object:
//------ myMethods.js ------
export default {
myMethod1() {
console.log('foo');
},
myMethod2(args...) {
console.log('bar');
}
};
I do recommend your second approach with multiple exports, though.
exporting everything individually does feel a bit verbose
Well, you don't need any wrapper structure, so I'd say it's less boilerplate. You just have to explicitly tag everything that you want to be exported, which is not a bad thing.
* as syntax is my preferred method as it allows you to use the dot notation (referencing both the module AND the method) aiding code readability.
That's very much personal preference, and does depend on the type of code you are writing. Sometimes conciseness is superior, but the ability to explicitly reference the module can be helpful as well. Notice that namespace imports using * as and default-imported objects are very similar here, though only named exports allow you to directly reference them via import {myMethod1, myMethod2}. So better leave the choice to those that import your module.
Does this have any performance implications?
Not much. Current ES6 implementations are not yet aiming for performance optimisations anyway.
In general, static identifiers are easier to resolve and optimise than property accesses[1], multiple named exports and partial imports could theoretically make JIT faster, and of course smaller files need less time to load if unused exports are removed during bundling. See here for details. There hardly will be noticeable performance differences, you should use what is better maintainable.
[1]: module namespaces (import * as ns) are static as well, even if ns.… looks like a dynamic property access
TLDR; Use multiple exported methods and explicit import.
#Bergi is right about not needing a class with static fields, only an object in your first case. However, this option is discouraged by Axel Rauschmayer:
Note that default-exporting objects is usually an anti-pattern (if you want to export the properties). You lose some ES6 module benefits (tree-shaking and faster access to imports).
Devs at Airbnb recommend named exports and explicit wildcrad import, see this thread: https://github.com/airbnb/javascript/issues/710#issuecomment-297840604

Leading Underscore transpiled wrong with es6 classes

I am experiencing a really weird behavior and can't even say which package to blame for it.
My setup: RequireJS project with the JSXTransformer and the jsx! plugin
I have an es6 class like this:
define([
'react'
], function(
React
) {
class MyComponent extends React.Component {
myMethod() {
otherObject.someMethod()._privateProp; // Yes, we need this accessing and have no influence on it
}
}
return MyComponent;
});
The transpiled output in the resulting bundle after running r.js is:
define('jsx!project/components/InputOutput',[
'react'
], function(
React
) {
var ____Class8=React.Component;for(var ____Class8____Key in ____Class8){if(____Class8.hasOwnProperty(____Class8____Key)){MyComponent[____Class8____Key]=____Class8[____Class8____Key];}}var ____SuperProtoOf____Class8=____Class8===null?null:____Class8.prototype;MyComponent.prototype=Object.create(____SuperProtoOf____Class8);MyComponent.prototype.constructor=MyComponent;MyComponent.__superConstructor__=____Class8;function MyComponent(){"use strict";if(____Class8!==null){____Class8.apply(this,arguments);}}
MyComponent.prototype.myMethod=function() {"use strict";
otherObject.someMethod().$MyComponent_privateProp;
};
return MyComponent;
});
Note how otherObject.someMethod().$MyComponent_privateProp; is written there. This obviously breaks because it is not a property on instances of MyComponent.
Add /** #preventMunge */ to the top of the file. See this GitHub issue:
Yes, sorry this is a non-standard fb-ism. For now you can work around this and toggle this feature off by putting /** #preventMunge */ at the top of your file -- but that's also a pretty big fb-ism. We should (a) turn this into a transform option (rather than a direct docblock directive) and (b) make it opt-in rather than opt-out (since it's non-standard).
For context: We munge all under-prefixed object properties on a per-module basis partly because our under-prefix convention applies to both objects and classes. Additionally, even if we wanted to lax the objects vs classes distinction, it's impossible to tell (in the general case) if a property is a reference to this since alias variables can occur (i.e. var self = this; self._stuff;).

does goog.require need to be duplicated in subclass if it's base class imports it

I have a sublcass that inherits a base class that imports the goog.string class. Given that the subclass inherits the base class does the subclass need to import the goog.string library in order to use it? I am assuming that would be redundant.
// Base class
goog.provide('baseClass')
goog.require('goog.string');
baseClass = function() {
}
// Subclass
goog.provide('subClass')
goog.require('baseClass')
goog.require('goog.string'); // do i need this in order to use goog.string?
baseClass = function() {
}
goog.inherits(subClass.prototype, baseClass);
It isn't required for your code to function now but it definitely causes maintenance headaches if you depend on the 'requires of your dependencies being there. If your super class no longer needs "goog.string" and removes it the 'require then your code breaks. Whether this matter to you is a question of scale, but being explicit about all of your dependencies is generally considered good practice.

Set of CoffeeScript/JavaScript classes and methods available to rest of Rails app

I'm using Rails 3.2.9. When I add CoffeeScript code to a .js.coffee file in the /app/assets/javascripts directory, I get the resulting JavaScript in all of my webpages. The problem is all the JavaScript is wrapped in:
(function() {
// my code
}).call(this);
So any methods I define are not visible in any other CoffeeScript code I write in other files. What's the proper way to write a set of reusable CoffeeScript classes and methods with Rails?
The simplest thing to do is to namespace all your classes. If your application is called "app" then in your initialization code before anything else happens:
// Set up the namespace.
window.app = { }
and then in all your .coffee files:
class app.Pancakes
#...
Then you'd have a global namespace and you'd reference everything through that namespace:
pancakes = new app.Pancakes
Similarly for simple functions:
app.where_is = (pancakes, house) -> ...
# And elsewhere...
x = app.where_is(...)
There are various ways of setting up and partially hiding the namespace but they're all variations on the above and simple namespacing plays nicely with the Rails asset pipeline.
Also, you can define classes within the coffeescript files like this:
class this.Person
constructor: (attr = {}) ->
...
In that way, the definitions are attached to the global namespace.

Categories