Extending Javascript with new syntax - javascript

Im working on a project in which i'm trying to simplify the syntax of an older package, i.e.:
I want to convert something like
digitalPulse(LED2,1,1000) to puck.LED.flash("red",1000)
Where LED2 is a red LED always. There are around 50 of these examples.
After investigating this online everything is pointing to building a transpiler/preprocessor. Is this the best method as these blocks of code will be used within files, an example of their usage could be.
let puck = new Puck();
if(...){
puck.LED.flash("green",1000);
else {
puck.LED.flash("red",1000);
}
Sidenote
This particular example would be converted to
if(...){
digitalPulse(LED1,1,1000)}
} else {
digitalPulse(LED2,1,1000)}
}
In addition to this there are also
setWatch(function(){
LED2.set();
}, BTN,{edge:"rising", repeat:true, debounce:50})
which should translate to below, which accepts other parsed code in the function such as below: Some functions such as onPress assume default values like in this case there is no need to specify BTN or the object containing edge, repeat and debounce
puck.onPress(function(){
puck.LED.on("red");
}
How can I approach this without overcomplicating it as ive already fallen down a rabbit hole of transpilers/preprocessors trying my own tokenization, parsing to generate an AST and transpiling, but ive not been successful and havent been able to find an example of this online to see exactly.
Is there a better approach to this problem can anybody recommend tools to assist with this or with direction of where I should be researching.

My understanding is that you want to migrate a legacy procedural code to modern object oriented Javascript.
The 1st thing is to understand what is the target:
nodejs: you don't need any preprocessor or transpilers to support Javascript classes
a web browser: excepting very old version like Internet Explorer, every modern browsers supports Javascript classes. So the following code doesn't need any preprocessor or transpilers:
const div = document.querySelector("div");
class Led {
constructor() {
}
flash(color, time) {
div.style.backgroundColor = color;
setTimeout(() => div.style.backgroundColor = "", time);
}
}
class Puck {
constructor() {
this.LED = new Led();
}
}
const puck = new Puck();
if(Math.random() > 0.5){
puck.LED.flash("green", 1000);
} else {
puck.LED.flash("red", 1000);
}
<div style="width: 100px; height: 100px">LED</div>
If you really need to target old browser versions, I suggest to use Babel as a transpiler.
Feel free to give more detail so I can give you a more appropriate answer.

Related

es5 modular design pattern to es6

I have a website with 100k users/day. Currently we are writing code in Jquery/Vanilla JS using the modular design pattern. A simple js to hide/show loader is as below
"use strict";
var loaderHandler = (function(){
var loader = document.getElementById('main_loader');
return{
showProcessLoader : function(){
loader.style.display = 'block';
loader.style.opacity = '0.5';
},
hideLoader : function(){
loader.style.display = 'none';
}
}
})();
docReady(function() {
loaderHandler.hideLoader();
});
Whenever I want to show loader at some place I just call loaderHandler.showProcessLoader(); and loaderHandler.hideLoader(); to hide it. Similarly, I have other JS files which are written using the same design pattern and I create a single minified JS using a gulp task from all the js that is required on that page. Currently, everything works fine and I am able to call one js file function inside the other without any problem.
I have decided to move my application to the latest es6 now I have the following issues/queries
What is the design pattern in es6 which will be equivalent to my modular design pattern?
I don't intend to rewrite my existing js files but write only new js in es6. So I want the new design pattern shouldn't interfere with the existing architecture and still provide me support to write new js files in es6.
Also, I still should be easily able to call one js file function in other when a single minified file for a page is created.
Edit - I am already using babel to transpile my es6 code to es5 equivalent
1) What is the design pattern in es6 which will be equivalent to my modular design pattern?
Design patterns aren't necessarily built into a language, they're just techniques that a language may or may not provide enough abstraction ability to accomplish. As it seems like you know based on question 2, any design pattern you could do before you can also do in ES6 and even vice versa. In fact, transpilers like babel take code writtin in es6 and convert it like magic to previous versions.
But what it really seems like is that you're eager to use some of the newest features available in ES6 and based on your code above it seems like you need some type of private variable and method encapsulation, which means classes are probably perfect for you.
Converting it is pretty simple, but the only thing you have to keep in mind is that you need to export a new instance of your class as compared to using an IIFE. With a class you'll also gain the ability to make multiple instances of your class if you want to or even do some inheritance, but with your current example there might not be a good use case for those features.
In the example below the id of the element is passed into the constructor, meaning you can re-use this class for any number of elements if you choose to or simply export a singleton instance.
class AbstractLoaderHandler{
constructor(el_id){
this.loader = document.getElementById(el_id)
}
showProcessLoader(){
this.loader.style.display = 'block';
this.loader.style.opacity = '0.5';
}
hideLoader(){
this.loader.style.display = 'none';
}
}
let loaderHandler = new AbstractLoaderHandler('main_loader');
loaderHandler.hideLoader();
<div id="main_loader">Hello World</div>
<button onClick="loaderHandler.showProcessLoader()">Show</button>
<button onclick="loaderHandler.hideLoader()">Hide</button>
3) Also, I still should be easily able to call one js file function in other when a single minified file for a page is created.
Keep in mind that this has to do entirely with the way in which you're bundling your files. All you really need to do to insure this is to keep whatever you create exposed as a global variable.

"Enhance" existing JS class in ECMAScript 2017 (Firefox v55)?

Basically I'm wondering whether it is possible to redefine a method at class level, not instance level, as sought here.
Just to make clear, also, I want to be able to call the original method (on this) from within the enhanced/replacement method.
I tried implementing the chosen answer, "decorating the constructor", but it doesn't appear to work in FF55's "SpiderMonkey" version of ES2017: I get a message saying the class "requires new".
Doing a bit of googling I found this article. This man talks about a whole bunch of concepts which I wasn't even aware existed in Javascript! My knowledge of JS hasn't gone much beyond the Javascript Definitive Guide 6th Edition, although I do use Promises and async/await a lot (I'm hoping a new edition of the JS Def Guide will come out one day...).
So are there any experts out there who know of a way to, essentially, "enhance" (i.e. re-engineer, not extend) existing JS classes in ES2017?
Let say you have a class named Original, which has a render method, which you want to update.
class Original {
render() {
return 'Original';
}
}
You can update it by changing the render method of the prototype of the Original function like so:
Original.prototype.render = function() {
return 'Changed';
}
If you want to add a new method to your class this is how you do it:
Original.prototype.print = function() {
return 'Printing...';
}
Then you can use these methods as usual.
const changed = new Original().render();
const printed = new Original().print();
Whoops... thanks to Dovydas for this. I was obviously having a mental block!
const superObserve = MutationObserver.prototype.observe;
MutationObserver.prototype.observe = function( target, config ){
console.log( 'blip');
superObserve.call( this, target, config );
}

Has b2DebugDraw and b2ContactListener been replaced in liquidfun.js?

I'm trying to replace my current Box2D library (box2dweb.js) with Google's LiquidFun library.
The major difference seems like they placed all the b2#ClassName# classes in the global scope instead of keeping them modular (in a Box2D.* namespace like box2dweb did).
BUT it also seems like they've omitted a few b2#ClassName#, two of which I was using from the Box2dWeb.js version:
b2DebugDraw, and;
b2ContactListener;
Are those deprecated / not fully implemented / forgotten?
Simply define the listener as an object of functions, like so:
var listener = {
BeginContactBody: function(contact) {
console.log(contact.GetFixtureA());
},
EndContactBody: function(contact) {
console.log(contact.GetFixtureA());
},
PostSolve: function(contact, impulse) {
},
PreSolve: function(contact, oldManifold) {
}
}
world.SetContactListener(listener);
looking at https://github.com/google/liquidfun/blob/master/liquidfun/Box2D/lfjs/jsBindings/Dynamics/b2World.js helped me solve this, so if you run into other c++ -> javascript translation issues, that's a good starting point.

Namespacing Hierarchy, Minify and Cross-Browser Compatibility

I've been using the following model for Namespacing my newest Scripts. So far, it has some distinct advantages that, while I'm sure could be replicated in other ways, really help to in my coding process. Unfortunately, I've come across a significant disadvantage... When using some JS compression utilities, they mangle the code badly enough that I must avoid many advantageous options. Luckily, the code I save with this model helps mitigate the "damages".
I'm still curious to know if there is a more viable solution as the min.js only fail consistently in Chrome/IE. I know the below is a little too abstract for some. Are there any experts that might point me in the right direction. I've used YUI, Packer and JSMin. JSMin works reliably, but is not nearly as efficient...
/* Global Namspace */
(function (T) {"use strict";
/* Top.Sub1 */
(function(S1) {
// ... Some methods (public/private)
/* Top.Sub1.Mini */
(function(M) {
// ... Some methods (public/private)
}(S1.Mini = S1.Mini || function(o){}));
}
(T.Sub1 = T.Sub1 || function(o){}));
/* Top.Sub2 */
(function(S2) {
// ... Some methods (public/private)
/* Top.Sub2.Mini1 */
(function(M1) {
// ... Some methods (public/private)
}(S2.Mini1 = S2.Mini1 || function(o) {}));
/* Top.Sub2.Mini2 */
(function(M2) {
// ... Some methods (public/private)
}(S2.Mini2 = S2.Mini2 || function(o) {}));
} (T.Sub2 = T.Sub2 || function(o) {}));
} (window.Namespace = window.Namespace || function(o){}));
UPDATE: The most common error I am faced with is "unexpected token" of various sorts.. sometimes a ')' and sometimes a '}'. Every once in a while, it is a '('. I haven't yet addressed gzip as I want this out of the way.
UPDATE 2: Have checked/removed ns with a Tidied-jsHint passing file and still does not minify correctly. It definitely has to do with this model... Does anyone have a clear answer as to why? If not, further recommendations are welcome. P.S. the Github has been updated with Tidied-jsHint passing code.
I'd say read this article about what needs to be done and what needs to be avoided for good minification – http://alistapart.com/article/javascript-minification-part-II
And then choose a proper modules framework like AMD or commonjs.
UPD. My main advice will be to use a linter on your code like http://jshint.com and adhere to a coding style like http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml It mostly comes with explanations of why something will break in certain sitautions. It's also going to make your code more approachable for open source contributors.
After testing nearly every option on every minifier I could get my hands on, the code minifies quite fine. (With and without the tidy, etc...) The issue comes when any of the minifiers try to replace or obfuscate symbols. In particular, it does not handle this for loop well:
for (i = 0; i < l; i++) {
_.points[i] = new S.Point(_, pts[i]);
}
Removal of the loop allows for the optimization to occur correctly.

About Node's code style

EDIT
thx to all the answers,
and finally I decide to use some tools like Step,
all I need is "flow control" and don't want any thing else which may slow down the performance (I don't know how much exactly it would effect or the effect just can be ignored).
So I just create a little tool for flow control:
line.js
/**
* Create the "next" function
*
* #param {Array} tasks
* #param {Number} index
* #param {Number} last
*/
var next = function(tasks, index, last) {
if (index == last) {
return tasks[index + 1];
}
else {
return function(data) {
var nextIndex = index + 1;
tasks[nextIndex](next(tasks, nextIndex, last), data);
};
}
};
/**
* Invoke functions in line.
*/
module.exports = function() {
var tasks = arguments,
last = tasks.length - 2;
tasks[0](next(tasks, 0, last));
};
usage:
var line = require("line.js");
line(function(next) {
someObj.find(function(err, docs) {
// codes
next(docs);
});
}, function(next, docs) {
// codes
});
Hope this helps.
EDIT END
As all know,
Node's built-in or third-part modules often provides async API,
and using "callback" function for dealing the results.
It's cool but sometimes would code like this:
//some codes
}
}
}
}
codes like this are hard to read.
I know "deferred" library can solve such problem,
Is there any good "deferred" module for Node?
And How is the performance if I code Node with "deferred"?
It is a large problem with Node-based code; you frequently grow "callback pyramids". There are several approaches to dealing with the problem:
Code style:
Use this annoyance as an opportunity to break your code into bite sized chunks. It means you're likely going to have a proliferation of tiny named funcs - that's probably just fine, though! You might also find more opportunities for reuse.
Flow-control Libraries
There are exactly 593.72 billion flow control libraries out there. Here's some of the more popular ones:
Step super basic serial & parallel flow management.
seq is a heavier but more feature-full flow control library.
There's plenty more. Search the npm registry for "flow" and "flow control" (sorry, doesn't appear to be linkable)
Language Extensions
There are several attempts to provide a more synchronous-feeling syntax on top of JavaScript (or CoffeeScript), often based on the concepts behind the tame paper.
TameJS is the OkCupid team's answer to this.
IcedCoffeeScript they've also ported TameJS over CoffeeScript as a fork.
streamline.js is very similar to TameJS.
StratifiedJS is a heavier approach to the problem.
This route is a deal-breaker for some:
It's not standard JavaScript; if you are building libraries/frameworks/etc, finding help will be more difficult.
Variable scope can behave in unexpected ways, depending on the library.
The generated code can be difficult to debug & match to the original source.
The Future:
The node core team is very aware of the problem, and are also working on lower level components to help ease the pain. It looks like they'll be introducing a basic version of domains in v0.8, which provide a way of rolling up error handling (avoiding the common return err if err pattern, primarily).
This should start to lay a great foundation for cleaner flow control libraries, and start to pave the way for a more consistent way of dealing with callback pyramids. There's too much choice out there right now, and the community isn't close to agreeing on even a handful of standards yet.
References:
Mixu's Node book has an awesome chapter on this subject.
There are tons of "deferred libraries". Have a look there http://eirikb.github.com/nipster/#promise and there http://eirikb.github.com/nipster/#deferred. To pick one, it's only a matter of style & simplicity :)
If you really don't like that, there's always the alternative of using named functions, which will reduce the indentation.
Instead of
setTimeout(function() {
fs.readFile('file', function (err, data) {
if (err) throw err;
console.log(data);
})
}, 200);
You can do this:
function dataHandler(err, data)
{
if (err) throw err;
console.log(data);
}
function getFile()
{
fs.readFile('file', dataHandler);
}
setTimeout(getFile, 200);
The same thing, no nesting.
There are some libraries that may be useful in some scenarios, but as a whole you won't be excited after using them for everything.
According to the slowness issues. Since node.js is async, the wrapped functions are not such a big performance consumer.
You could look here for deferred-like library
https://github.com/kriszyp/node-promise
Also this question is very similar
What nodejs library is most like jQuery's deferreds?
And as a final bonus I suggest you take a look at CoffeeScript. It is a language, which compiles to javascript and has more beautiful syntax, since the function braces are removed
I usually like to use the async.js library as it offers a few different options on how to execute the code

Categories

Resources