I had one big class that I split in two and load them separately on a page to improve performance. Core part is loaded first synchronously as it contains critical functionality while Extension (non-critical functionality) loads later in the page asynchronously.
I want only one object which contains functionality of both classes. But by the time Extension loads, there's already an object of Core. How do I add functionality from Extension onto the object of Core?
I'm using a Gulp based asset pipeline with
Rollup = to bundle the JS from different files into one file
Babel = to transpile ES6 to ES5
Uglify = to minimize the JS
Here's my directory structure:
js
|_ _classes
| |_ ab.js
| |_ cd.js
|_ core.js
|_ ext.js
I have set the gulp build task to ignore files in "_classes" directory. Rollup parses the "import" statements to bundle the code.
This is what I have in core.js
//core.js
import AB from './_classes/ab.js';
window.oab = new AB();
and this is ext.js
//ext.js
import CD from './_classes/cd.js';
//let o_cd = new CD();
window.oab.prototype = CD;
This is the Core class
// file ab.js
class AB {
constructor() {
this.car = 'McLaren';
this.fruit = 'Mango';
}
getCar() {
return this.car;
}
getFruit() {
return this.fruit;
}
}
and this is the Extension class
//file cd.js
class CD {
constructor() {
this.plane = 'Gulfstream';
}
getPlane() {
return this.plane;
}
}
I'm trying to get this to work:
console.log( window.oab.getCar() ); // prints McLaren
console.log( window.oab.getFruit() ); // prints Mango
console.log( window.oab.getPlane() ); // prints Gulfstream
Now I can very well import the AB
class in CD
class, set CD
class to extend AB
and that will give me what I want. But with my current gulp pipeline setup, that would mean that Rollup would bundle a copy of class AB
with class CD
as well and class AB
has already loaded earlier.
Due to Rollup, Babel & Uglify, the class names AB
& CD
etc don't persist, so I cannot assume AB
being available in CD
for me to extend without importing it first and importing it would mean it being bundled with CD
.
I applied a monkey patch in ext.js
on window.oab
and this gives me what I'm looking for.
import CD from './_classes/cd.js';
( function() {
let i;
let ocd = new CD();
let ocd_methods = Object.getOwnPropertyNames( ocd.__proto__ ).filter( p => {
return ( 'function' === typeof ocd.__proto__[ p ] );
});
Object.assign( window.oab, ocd ); // this assigns only properties of ocd into window.oab and not the methods
for ( i in ocd_methods ) {
let method = ocd_methods[ i ];
if ( '__proto__' === method || 'constructor' === method ) {
continue;
}
window.oab.__proto__[ method ] = ocd[ method ];
}
} () );
And now this works
console.log( window.oab.getCar() ); // prints McLaren
console.log( window.oab.getFruit() ); // prints Mango
console.log( window.oab.getPlane() ); // prints Gulfstream