Skip to content

Instantly share code, notes, and snippets.

@tolu
Last active September 10, 2018 08:32
Show Gist options
  • Save tolu/cde578e427f38e5adbd64724b36a1eb3 to your computer and use it in GitHub Desktop.
Save tolu/cde578e427f38e5adbd64724b36a1eb3 to your computer and use it in GitHub Desktop.
Modern javascript examples with old counterparts
// Because of the inheritance model of js it's possible
// to create abstract base classes that can in principle behave as interfaces
class IPage {
constructor(){
if(new.target === IPage){ throw Error('Cant create instance of interface (abstract class)'); }
}
getTitle(){ throw new Error(this.name + ' not implemented'); }
getClasses(){ throw new Error(this.name + ' not implemented'); }
getContent(){ throw new Error(this.name + ' not implemented'); }
}
class MyPage extends IPage {
getTitle(){ console.log('title implemented'); }
getClasses(){ console.log('classe ok');}
}
try {
var page = new IPage();
} catch(e){} // ERROR!!!
try {
(new MyPage()).getContent();
} catch(e){} // NotImplementedException
// Using this technique one can provide interfaces for interacting with libraries or whatever
/* ES5 prototype way */
// constructor
var Person = function(name){
// instance variables
this.name = name;
}
// prototype methods
Person.prototype.sayName = function(){
console.log(this.name);
}
/* ES6 class emulation */
let PersonType = (function(){
// classes are always in strict mode
'use strict';
// disallow overriding internal name
const PersonType = function(name){
// make sure calle with new
if(typeof new.target === 'undefined') {
throw new Error('Constructor must be called with new');
}
this.name = name;
}
Objec.definedProperty(PersonType.prototype, 'sayName', {
value: function(){
if(typeof new.target !== 'undefined') {
throw new Error('Methods cannot be called with new');
}
console.log(this.name);
},
enumerable: false,
writeable: true,
configurable: true
});
return PersonType;
}());
/* Using ES6 Class */
class PersonClass {
constructor(name){
this.name = name;
}
sayName(){
console.log(this.name);
}
}
/* For serial asynchhronous coding */
// usage - now this looks more like async await
runTask(function*(){
let content = yield readFile('some.json');
let result = yield operateOnJson(content);
doSomethingWithResult(result);
console.log('done')!
})
function runTask(taskDef){
// create iterator
let task = taskDef();
// start task
let result = task.next();
// recursive function to keep calling next
function step(){
if(!result.done){
// if value is function assume it takes callback and execute
if(typeof result.value === 'function'){
result.value(function(err, data){
if(err){
result = task.throw(err);
return
}
// assign result to pass results based on earlier tasks available down the line
result = task.next(data);
step();
});
} else {
result = task.next(result.value);
step();
}
}
}
// start process
step();
}
// create functions that returns function and accepts callback
function readFile(fileName){
return function(callback){
fs.readFile(filename, callback);
}
}
function operateOnJson(json){
return function(callback){
// do something with data
const changedJson = Obect.assign({}, json, { newProp: 'hey!'});
// add timeout for good measure
setTimeout(() => {
callback(null, changedJson);
},250)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment