6 questions โ Basic to Advanced ยท Click to expand ยท + for code & details
var is function-scoped, can be redeclared and re-assigned, and is hoisted to the top of its function (initialized as undefined). let is block-scoped, cannot be redeclared in the same scope, can be re-assigned, and is hoisted but not initialized (temporal dead zone). const is block-scoped, cannot be redeclared or re-assigned after declaration, but object/array contents can be mutated.
Modern JavaScript best practice: use const by default, let when reassignment is needed, never var.
// var: function-scoped, hoisted
function example() {
console.log(x); // undefined (hoisted)
var x = 10;
if (true) {
var x = 20; // same x! overwrites
}
console.log(x); // 20
}
// let: block-scoped
function modern() {
let y = 10;
if (true) {
let y = 20; // different y (block scope)
console.log(y); // 20
}
console.log(y); // 10
}
// const: cannot reassign
const MAX = 100;
// MAX = 200; // TypeError!
const obj = { name: 'Alice' };
obj.name = 'Bob'; // OK: mutating object, not reassigning const
obj.salary = 50000; // OK: adding property
console.log(obj); // { name: 'Bob', salary: 50000 }| EMP_ID | EMP_NAME | DEPT_ID | SALARY |
|---|---|---|---|
| 101 | Alice Johnson | 10 | 50,000 |
| 102 | Bob Smith | 20 | 62,000 |
| 103 | Carol White | 10 | 55,000 |
| 104 | Dave Brown | 20 | 70,000 |
All 4 rows returned from employees table
var is function-scoped, can be redeclared and re-assigned, and is hoisted to the top of its function (initialized as undefined).
Arrow functions are a concise syntax for writing functions introduced in ES6.
Key differences from regular functions: arrow functions do not have their own this binding (they inherit this from the enclosing scope), they cannot be used as constructors (no new keyword), they have no arguments object, and they cannot be used as generator functions.
Arrow functions are ideal for callbacks and methods where this context matters, like event handlers and array methods.
// Regular function
function add(a, b) {
return a + b;
}
// Arrow function equivalents
const add = (a, b) => a + b; // implicit return
const square = n => n * n; // single param, no parens needed
const greet = () => 'Hello World'; // no params
const getObj = () => ({ name: 'Alice' }); // return object literal
// this binding difference
const timer = {
count: 0,
// Regular: 'this' is undefined in strict mode callback
startBad: function() {
setTimeout(function() {
this.count++; // 'this' is window/undefined!
}, 1000);
},
// Arrow: inherits 'this' from startGood
startGood: function() {
setTimeout(() => {
this.count++; // 'this' is timer object โ
}, 1000);
}
};
// Array methods: arrow functions shine
const salaries = [50000, 62000, 55000];
const doubled = salaries.map(s => s * 2);
const high = salaries.filter(s => s > 55000);| EMP_ID | EMP_NAME | DEPT_ID | SALARY |
|---|---|---|---|
| 101 | Alice Johnson | 10 | 50,000 |
| 102 | Bob Smith | 20 | 62,000 |
| 103 | Carol White | 10 | 55,000 |
| 104 | Dave Brown | 20 | 70,000 |
All 4 rows returned from employees table
Arrow functions are a concise syntax for writing functions introduced in ES6.
A Promise represents a value that may not be available yet โ it is either pending, fulfilled (resolved), or rejected.
Promises replaced callback hell for asynchronous code. async/await is syntactic sugar over Promises making async code look synchronous.
An async function always returns a Promise. await pauses execution until the Promise settles.
Use try/catch for error handling with async/await.
This is widely used in APEX's apex.server.process callbacks and fetch API calls.
// Promise
function fetchEmployee(id) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (id > 0) resolve({ id, name: 'Alice', salary: 50000 });
else reject(new Error('Invalid ID'));
}, 1000);
});
}
// Using .then/.catch
fetchEmployee(101)
.then(emp => console.log('Found:', emp.name))
.catch(err => console.error('Error:', err.message));
// async/await (cleaner)
async function loadEmployee(id) {
try {
const emp = await fetchEmployee(id);
console.log('Name:', emp.name);
console.log('Salary:', emp.salary);
return emp;
} catch (err) {
console.error('Failed:', err.message);
}
}
// APEX: apex.server.process with async/await
async function saveRecord() {
const result = await apex.server.process('SAVE_EMP', {
pageItems: '#P1_EMP_NAME,#P1_SALARY'
});
apex.message.showPageSuccess('Saved: ' + result.emp_id);
}| EMP_ID | EMP_NAME | DEPT_ID | SALARY |
|---|---|---|---|
| 101 | Alice Johnson | 10 | 50,000 |
| 102 | Bob Smith | 20 | 62,000 |
| 103 | Carol White | 10 | 55,000 |
| 104 | Dave Brown | 20 | 70,000 |
All 4 rows returned from employees table
A Promise represents a value that may not be available yet โ it is either pending, fulfilled (resolved), or rejected.
The DOM (Document Object Model) is a programming interface that represents an HTML document as a tree of objects.
Every HTML element, attribute, and text node is a DOM node.
JavaScript can read and modify the DOM to dynamically update pages.
Key methods include querySelector/querySelectorAll (find elements), createElement (create new elements), appendChild/insertBefore (add to DOM), removeChild/remove (delete), setAttribute, classList, and innerHTML/textContent.
In APEX, most DOM manipulation happens via Dynamic Actions.
// Find elements
const header = document.getElementById('main-header');
const buttons = document.querySelectorAll('.action-btn');
const firstBtn = document.querySelector('.action-btn');
// Read/modify content
console.log(header.textContent); // read text
header.textContent = 'New Title'; // set text
header.innerHTML = '<em>Styled</em>'; // set HTML
header.style.color = '#2d6446'; // set style
// Classes
header.classList.add('active');
header.classList.remove('hidden');
header.classList.toggle('expanded');
header.classList.contains('active'); // true/false
// Create and add elements
const card = document.createElement('div');
card.className = 'employee-card';
card.dataset.id = '101';
card.textContent = 'Alice Johnson';
document.getElementById('emp-list').appendChild(card);
// Remove element
card.remove();
// APEX: get item value via DOM
const deptId = document.getElementById('P1_DEPT_ID').value;| EMP_ID | EMP_NAME | DEPT_ID | SALARY |
|---|---|---|---|
| 101 | Alice Johnson | 10 | 50,000 |
| 102 | Bob Smith | 20 | 62,000 |
| 103 | Carol White | 10 | 55,000 |
| 104 | Dave Brown | 20 | 70,000 |
All 4 rows returned from employees table
The DOM (Document Object Model) is a programming interface that represents an HTML document as a tree of objects.
A closure is a function that has access to variables from its outer (enclosing) scope even after the outer function has returned.
Closures are created every time a function is created in JavaScript.
They are used for data privacy (module pattern), factory functions, memoization, and event handlers that need to reference outer variables.
Understanding closures is crucial for writing APEX Dynamic Action JavaScript and maintaining state in callbacks.
// Basic closure
function makeCounter(start = 0) {
let count = start; // 'count' is enclosed
return {
increment: () => ++count,
decrement: () => --count,
getCount: () => count,
reset: () => { count = start; }
};
}
const counter = makeCounter(10);
console.log(counter.increment()); // 11
console.log(counter.increment()); // 12
console.log(counter.decrement()); // 11
console.log(counter.getCount()); // 11
// 'count' is private โ can't access directly
// Closure in APEX event handler
function attachSaveHandler(empId, empName) {
// empId, empName are enclosed in the click handler
document.getElementById('save-btn')
.addEventListener('click', function() {
// Still has access to empId and empName
apex.server.process('SAVE', {
x01: empId,
x02: empName
});
});
}
attachSaveHandler(101, 'Alice');| EMP_ID | EMP_NAME | DEPT_ID | SALARY |
|---|---|---|---|
| 101 | Alice Johnson | 10 | 50,000 |
| 102 | Bob Smith | 20 | 62,000 |
| 103 | Carol White | 10 | 55,000 |
| 104 | Dave Brown | 20 | 70,000 |
All 4 rows returned from employees table
A closure is a function that has access to variables from its outer (enclosing) scope even after the outer function has returned.
The Fetch API is a modern, Promise-based way to make HTTP requests in the browser, replacing the older XMLHttpRequest. fetch() takes a URL and optional options object and returns a Promise that resolves to a Response object.
You must call .json(), .text(), or .blob() on the Response to extract the body (which is also a Promise).
Fetch does not reject on HTTP error codes (4xx/5xx) โ you must check response.ok.
In APEX, use apex.server.process for AJAX instead of raw fetch for session handling.
// Basic GET request
async function getEmployee(id) {
const response = await fetch(`/api/employees/${id}`);
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
const data = await response.json();
return data;
}
// POST request with JSON body
async function createEmployee(empData) {
const response = await fetch('/api/employees', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
},
body: JSON.stringify(empData)
});
return response.json();
}
// APEX: use apex.server.process (handles session)
apex.server.process('GET_EMPLOYEE', { x01: empId }, {
success: function(data) {
$("#P1_EMP_NAME").val(data.emp_name);
},
error: function(xhr) {
console.error('APEX process failed:', xhr.status);
}
});| EMP_ID | EMP_NAME | DEPT_ID | SALARY |
|---|---|---|---|
| 101 | Alice Johnson | 10 | 50,000 |
| 102 | Bob Smith | 20 | 62,000 |
| 103 | Carol White | 10 | 55,000 |
| 104 | Dave Brown | 20 | 70,000 |
All 4 rows returned from employees table
The Fetch API is a modern, Promise-based way to make HTTP requests in the browser, replacing the older XMLHttpRequest.