Master 9 Essential JavaScript Techniques: Dynamic Loading, Templates, Reduce, and More
This article walks through nine practical JavaScript patterns—including dynamic script loading, a lightweight template engine, data transformation with reduce, default parameters, one‑time execution, currying, singleton implementation, a simple CommonJS loader, and recursive property access—providing clear code examples for each.
1. Dynamic JS File Loading
In certain scenarios, especially when developing libraries or frameworks, you may need to load and execute JS files dynamically. Below is a simple Promise‑based wrapper.
<code>function loadJS(files, done) {
const head = document.getElementsByTagName('head')[0];
Promise.all(files.map(file => new Promise(resolve => {
const s = document.createElement('script');
s.type = "text/javascript";
s.async = true;
s.src = file;
s.addEventListener('load', () => resolve(), false);
head.appendChild(s);
}))).then(done);
}
loadJS(["test1.js", "test2.js"], () => {
// user's callback logic
});</code>2. Implementing a Template Engine
This concise example demonstrates a dynamic template rendering engine that supports variable substitution as well as JS logic such as loops and conditionals.
<code>var template =
'My favorite sports:' +
'<%if(this.showSports) {%>' +
'<% for(var index in this.sports) { %>' +
'<a><%this.sports[index]%></a>' +
'<%}%>' +
'<%} else {%>' +
'<p>none</p>' +
'<%}%>';
const code = `with(obj) {
var r=[];
r.push("My favorite sports:");
if(this.showSports){
for(var index in this.sports){
r.push("<a>");
r.push(this.sports[index]);
r.push("</a>");
}
} else {
r.push("<span>none</span>");
}
return r.join("");
}`;
const options = { sports:["swimming","basketball","football"], showSports:true };
const result = new Function("obj", code).apply(options, [options]);
console.log(result);
</code>3. Using Reduce to Transform Data Structures
Reduce is a powerful tool for reshaping data received from back‑end services. The example groups an array of objects by a specified key.
<code>const arr = [
{ classId:"1", name:"Jack", age:16 },
{ classId:"1", name:"Jon", age:15 },
{ classId:"2", name:"Jenny", age:16 },
{ classId:"3", name:"Jim", age:15 },
{ classId:"2", name:"Zoe", age:16 }
];
function groupArrayByKey(arr = [], key) {
return arr.reduce((t, v) => (
(!t[v[key]] && (t[v[key]] = []),
t[v[key]].push(v),
t)
), {});
}
console.log(groupArrayByKey(arr, "classId"));
</code>4. Adding Default Values
Functions can provide default arguments or enforce required parameters.
<code>function double(value = 0) {
return value * 2;
}
const required = () => { throw new Error("This function requires one parameter."); };
function double(value = required()) {
return value * 2;
}
console.log(double(3)); // 6
console.log(double()); // throws Error
</code>5. Ensuring a Function Executes Only Once
<code>export function once(fn) {
let called = false;
return function() {
if (!called) {
called = true;
fn.apply(this, arguments);
}
};
}
</code>6. Implementing Curry
Curry transforms a multi‑parameter function into a sequence of single‑parameter functions, improving reusability.
<code>function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
} else {
return function(...args2) {
return curried.apply(this, args.concat(args2));
};
}
};
}
function add(x, y) { return x + y; }
const curriedAdd = curry(add);
console.log(curriedAdd(1)(2)); // 3
console.log(curriedAdd(1, 2)); // 3
</code>7. Implementing the Singleton Pattern
<code>let cache;
class A { /* ... */ }
function getInstance() {
if (cache) return cache;
return cache = new A();
}
const x = getInstance();
const y = getInstance();
console.log(x === y); // true
</code>8. Simple CommonJS Implementation
The core idea of CommonJS is to treat each file as a module with its own scope. The following code provides a minimal implementation of a module loader.
<code>const path = require('path');
const fs = require('fs');
function Module(id) {
this.id = id;
this.exports = {};
}
function myRequire(filePath) {
return Module._load(filePath);
}
Module._cache = {};
Module._load = function(filePath) {
const realPath = Module._resolveFilename(filePath);
if (Module._cache[realPath]) return Module._cache[realPath].exports;
const module = new Module(realPath);
module.load(realPath);
return module.exports;
};
Module._extensions = {
'.js': handleJS,
'.json': handleJSON
};
function handleJSON(module) {
const json = fs.readFileSync(module.id, 'utf-8');
module.exports = JSON.parse(json);
}
function handleJS(module) {
const js = fs.readFileSync(module.id, 'utf-8');
const fn = new Function('exports','myRequire','module','__filename','__dirname', js);
fn.call(module.exports, module.exports, myRequire, module, module.id, path.dirname(module.id));
}
Module._resolveFilename = function(filePath) {
let absPath = path.resolve(__dirname, filePath);
if (fs.existsSync(absPath)) return absPath;
const keys = Object.keys(Module._extensions);
for (let i = 0; i < keys.length; i++) {
const currentPath = absPath + keys[i];
if (fs.existsSync(currentPath)) return currentPath;
}
};
Module.prototype.load = function(realPath) {
const extname = path.extname(realPath);
Module._extensions[extname](this);
};
</code>9. Recursively Getting Object Properties
A utility function that retrieves nested properties safely, returning a fallback value when the path does not exist.
<code>function get(obj, path, fallback) {
const parts = path.split('.');
const key = parts.shift();
if (typeof obj[key] !== 'undefined') {
return parts.length > 0 ? get(obj[key], parts.join('.'), fallback) : obj[key];
}
return fallback;
}
const user = { info: { name: "Jacky", address: { home: "MLB", company: "AI" } } };
console.log(get(user, "info.name")); // Jacky
console.log(get(user, "info.address.home")); // MLB
console.log(get(user, "info.address.company")); // AI
console.log(get(user, "info.address.abc", "fallback")); // fallback
</code>Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.