Day 40/50 – JavaScript Interview Question? Question: What is the Map object and how does it differ from a plain Object? Simple Answer: A Map is a key-value collection where keys can be any type (objects, functions, primitives). Unlike plain objects, Maps maintain insertion order, have a size property, are iterable by default, and don't have prototype chain issues. 🧠 Why it matters in real projects: Maps are superior for frequently adding/removing entries, using non-string keys (like objects or DOM elements), maintaining order, and avoiding prototype pollution. They're essential for caching, memoization, and when you need dictionary-like behavior with better performance. 💡 One common mistake: Using objects as dictionaries when Map would be more appropriate, especially when keys might collide with prototype properties like toString or constructor. Also, forgetting that object keys are always converted to strings. 📌 Bonus: // Creating Maps const map = new Map(); map.set('name', 'Alice'); map.set(42, 'number key'); map.set(true, 'boolean key'); // Objects as keys (impossible with plain objects!) const objKey = { id: 1 }; map.set(objKey, 'object value'); // Basic operations map.get('name'); // 'Alice' map.has(42); // true map.delete(true); // Remove entry map.size; // 3 (not length) map.clear(); // Remove all // Key differences from Objects: // 1. Any type as key const func = () => {}; map.set(func, 'function key'); // ✓ Works! const obj = { [func]: 'test' }; // ✗ Converts to string // 2. Size property (O(1)) map.size; // Instant Object.keys(obj).length; // O(n) - slower // 3. Iteration order guaranteed const map2 = new Map(); map2.set('z', 1); map2.set('a', 2); map2.set('m', 3); for (let [key, value] of map2) { console.log(key); // 'z', 'a', 'm' (insertion order) } // 4. No prototype pollution const obj2 = {}; obj2.toString = 'hacked'; // Problem! const map3 = new Map(); map3.set('toString', 'safe'); // No issues // Practical use cases: // Caching with object keys const cache = new Map(); function expensiveOp(obj) { if (cache.has(obj)) { return cache.get(obj); } const result = /* expensive calculation */; cache.set(obj, result); return result; } // Counting occurrences const count = new Map(); for (let item of items) { count.set(item, (count.get(item) || 0) + 1); } // Converting between Object and Map const obj3 = { a: 1, b: 2 }; const map4 = new Map(Object.entries(obj3)); const obj4 = Object.fromEntries(map4); // When to use Map vs Object: // Use Map: frequent add/delete, non-string keys, need size // Use Object: static structure, JSON serialization, prototype methods #JavaScript #WebDevelopment #Frontend #LearnInPublic #InterviewQuestions #Programming #TechInterviews #Map #DataStructures #InterviewPrep #ES6
JavaScript Map vs Object: Key Differences and Use Cases
More Relevant Posts
-
Day 41/50 – JavaScript Interview Question? Question: What is the WeakMap and WeakSet, and when should you use them? Simple Answer: WeakMap and WeakSet are collections that hold "weak" references to objects, meaning if there are no other references to an object, it can be garbage collected. Keys in WeakMap and values in WeakSet must be objects (not primitives), and they're not iterable. 🧠 Why it matters in real projects: WeakMaps prevent memory leaks when associating metadata with DOM elements or objects. They're crucial in frameworks like Vue 3 for reactivity systems, storing private data, and caching without preventing garbage collection. When an object is removed, its WeakMap entries disappear automatically. 💡 One common mistake: Trying to use primitive values as keys in WeakMap or storing primitives in WeakSet (throws TypeError). Also expecting to iterate over WeakMap/WeakSet—they don't have .forEach(), .keys(), or .size to prevent memory management interference. 📌 Bonus: // Regular Map - prevents garbage collection const map = new Map(); let obj = { data: 'large object' }; map.set(obj, 'metadata'); obj = null; // Object still in memory! (referenced by map) // WeakMap - allows garbage collection const weakMap = new WeakMap(); let obj2 = { data: 'large object' }; weakMap.set(obj2, 'metadata'); obj2 = null; // Object can be garbage collected ✓ // Practical use cases: // 1. Private data storage const privateData = new WeakMap(); class User { constructor(name, ssn) { this.name = name; privateData.set(this, { ssn }); // Private! } getSSN() { return privateData.get(this).ssn; } } // 2. DOM element metadata (prevents memory leaks) const elementMetadata = new WeakMap(); function attachMetadata(element, data) { elementMetadata.set(element, data); } const div = document.querySelector('#myDiv'); attachMetadata(div, { clicks: 0 }); // When div is removed from DOM, metadata is auto-cleaned // 3. Caching with automatic cleanup const cache = new WeakMap(); function processObject(obj) { if (cache.has(obj)) { return cache.get(obj); } const result = expensiveComputation(obj); cache.set(obj, result); return result; } // WeakSet example - tracking objects const visitedNodes = new WeakSet(); function traverse(node) { if (visitedNodes.has(node)) return; visitedNodes.add(node); // Process node... node.children.forEach(traverse); } // Limitations: // ✗ Can't use primitives weakMap.set('string', 'value'); // TypeError! // ✗ Can't iterate weakMap.forEach(...); // undefined (doesn't exist) weakMap.size; // undefined // ✗ Can't clear all at once weakMap.clear(); // undefined (doesn't exist) #JavaScript #WebDevelopment #Frontend #LearnInPublic #InterviewQuestions #Programming #TechInterviews #myDiv #WeakMap #MemoryManagement #WebDev #AdvancedJS
To view or add a comment, sign in
-
Day 42/50 – JavaScript Interview Question? Question: What is the Temporal Dead Zone (TDZ) and why does it exist? Simple Answer: The Temporal Dead Zone is the period from entering a scope until a let or const variable is declared. During this time, accessing the variable throws a ReferenceError. It exists to catch errors early and make code more predictable. 🧠 Why it matters in real projects: Understanding TDZ helps debug confusing ReferenceErrors and explains why let/const behave differently from var. It enforces better coding practices by preventing access to uninitialized variables, making bugs more obvious during development rather than in production. 💡 One common mistake: Assuming let and const aren't hoisted because of TDZ. They ARE hoisted, but remain uninitialized in the TDZ. Also, using variables before declaration in complex scopes and getting unexpected ReferenceErrors. 📌 Bonus: // var - no TDZ (hoisted with undefined) console.log(varVariable); // undefined var varVariable = 'Hello'; // let/const - TDZ exists console.log(letVariable); // ReferenceError! let letVariable = 'World'; // TDZ in block scope function example() { // TDZ starts here for 'x' console.log(x); // ReferenceError: Cannot access before initialization let x = 10; // TDZ ends here console.log(x); // 10 } // Tricky TDZ scenario let x = 'outer'; function test() { // TDZ for inner 'x' starts here console.log(x); // ReferenceError! (not 'outer') let x = 'inner'; // TDZ ends } // Why TDZ exists: // 1. Catch errors early function process() { console.log(value); // Intentional? Typo? TDZ makes it obvious! let value = 42; } // 2. Make const meaningful const PI = 3.14159; // Without TDZ, accessing PI before declaration would give undefined // making const less useful // 3. Prevent confusing behavior function confusing() { // What should this print? function getValue() { return value; // 'outer' or ReferenceError? } let value = 'inner'; console.log(getValue()); } // typeof operator gotcha console.log(typeof undeclaredVar); // "undefined" - safe console.log(typeof declaredLater); // ReferenceError! - TDZ let declaredLater = 10; // Best practices: // ✓ Declare variables at the top of their scope function betterCode() { let x, y, z; // Declare first x = getValue(); y = processData(x); z = x + y; } // ✓ Use const by default, let when needed const config = { api: '/api' }; // Won't reassign let counter = 0; // Will change #JavaScript #WebDevelopment #Frontend #LearnInPublic #InterviewQuestions #Programming #TechInterviews #TDZ #ES6 #InterviewPrep #Hoisting
To view or add a comment, sign in
-
Day 45/50 – JavaScript Interview Question? Question: What is the difference between call(), apply(), and bind()? Simple Answer: All three set the this context explicitly. call(thisArg, arg1, arg2, ...) invokes immediately with individual arguments. apply(thisArg, [args]) invokes immediately with an array of arguments. bind(thisArg) returns a new function with this permanently bound, without invoking. Why it matters in real projects: These methods are essential for method borrowing, event handlers with correct context, React class component methods, and functional programming patterns. Understanding them prevents common this binding bugs and enables powerful composition techniques. One common mistake: Confusing when to use each method. Use call when you know arguments, apply when you have an array, and bind when you need a reusable function with fixed context. Also, forgetting that arrow functions can't have their this rebound. Bonus: const person = { name: 'Alice', greet(greeting, punctuation) { console.log(`${greeting}, ${ this.name }${punctuation}`); } }; const person2 = { name: 'Bob' }; // call() - invoke immediately with individual args person.greet.call(person2, 'Hello', '!'); // "Hello, Bob!" // apply() - invoke immediately with array person.greet.apply(person2, ['Hi', '?']); // "Hi, Bob?" // bind() - return new function (doesn't invoke) const greetBob = person.greet.bind(person2); greetBob('Hey', '.'); // "Hey, Bob." // Practical use cases: // 1. Method borrowing const arrayLike = { 0: 'a', 1: 'b', length: 2 }; const arr = Array.prototype.slice.call(arrayLike); console.log(arr); // ['a', 'b'] // Modern alternative const arr2 = Array.from(arrayLike); // 2. Finding max/min with apply const numbers = [5, 2, 9, 1, 7]; const max = Math.max.apply(null, numbers); // 9 // Modern alternative const max2 = Math.max(...numbers); // 3. Event handlers with correct context class Button { constructor(label) { this.label = label; this.clicks = 0; } handleClick() { this.clicks++; console.log(`${this.label}: ${this.clicks} clicks`); } render() { const btn = document.createElement('button'); // ✗ Wrong - loses context btn.addEventListener('click', this.handleClick); // ✓ Right - preserves context btn.addEventListener('click', this.handleClick.bind(this)); } } // 4. Partial application with bind function multiply(a, b) { return a * b; } const double = multiply.bind(null, 2); console.log(double(5)); // 10 console.log(double(10)); // 20 // 5. Function composition function add(x, y) { return x + y; } const add5 = add.bind(null, 5); const result = [1, 2, 3].map(add5); // [6, 7, 8] // Polyfill for bind (interview favorite) Function.prototype.myBind = function(context, ...args) { const fn = this; return function(...newArgs) { return fn.apply(context, [...args, ...newArgs]); }; }; // Arrow functions can't be rebound const arrowFunc = () => { console.log(this.name); }; const obj = { name: 'Test' }; arrowFunc.call(obj); // Won't bind 'this' to obj!
To view or add a comment, sign in
-
Day 48/50 – JavaScript Interview Question? Question: What is the difference between shallow copy and deep copy? How do you implement each? Simple Answer: Shallow copy duplicates top-level structure but keeps references to nested objects. Deep copy recursively duplicates all nested objects. Shallow: spread operator, Object.assign(). Deep: structuredClone(), JSON.parse(JSON.stringify()), or custom recursion. 🧠 Why it matters in real projects: Wrong copy method causes bugs in state management (React/Redux), data manipulation, and form handling. Shallow copies are fast but dangerous with nested data. Deep copies prevent mutations but can be expensive. 💡 One common mistake: Using spread operator for nested objects expecting deep copy. Mutations affect the original! Also using JSON.parse(JSON.stringify()) which fails for functions, dates, undefined, and circular references. 📌 Bonus: const original = { name: 'Alice', address: { city: 'NYC' }, hobbies: ['reading'] }; // Shallow copy - nested objects still shared const shallow = { ...original }; shallow.address.city = 'LA'; console.log(original.address.city); // 'LA' - Oops! // Deep copy - Modern way (best!) const deep = structuredClone(original); deep.address.city = 'Boston'; console.log(original.address.city); // 'NYC' - ✓ Independent! // JSON method (has limitations) const deep2 = JSON.parse(JSON.stringify(original)); // ✗ Loses functions const obj = { fn: () => {} }; JSON.parse(JSON.stringify(obj)); // {} - lost! // ✗ Breaks dates const obj2 = { date: new Date() }; JSON.parse(JSON.stringify(obj2)); // date becomes string! // Custom deep clone (interview favorite) function deepClone(obj, hash = new WeakMap()) { if (obj === null || typeof obj !== 'object') return obj; if (hash.has(obj)) return hash.get(obj); // Circular ref if (obj instanceof Date) return new Date(obj); if (Array.isArray(obj)) { const arr = []; hash.set(obj, arr); obj.forEach((item, i) => arr[i] = deepClone(item, hash)); return arr; } const copy = {}; hash.set(obj, copy); Object.keys(obj).forEach(key => { copy[key] = deepClone(obj[key], hash); }); return copy; } #JavaScript #WebDevelopment #Frontend #LearnInPublic #InterviewQuestions #Programming #TechInterviews
To view or add a comment, sign in
-
Day 47/50 – JavaScript Interview Question? Question: What is the difference between prototype and __proto__? Simple Answer: prototype is a property on constructor functions containing the object used as prototype for new instances. __proto__ is the actual internal link on every object pointing to its prototype. Use Object.getPrototypeOf() instead of __proto__. 🧠 Why it matters in real projects: Understanding the prototype chain explains how JavaScript inheritance works, how methods like .map() are available on arrays, and how classes work under the hood. Essential for creating efficient object hierarchies. 💡 One common mistake: Confusing prototype with __proto__, or modifying Object.prototype which affects all objects globally. Also using deprecated __proto__ instead of standard Object.getPrototypeOf(). 📌 Bonus: // Constructor function function Person(name) { this.name = name; } Person.prototype.greet = function() { return `Hello, I'm ${this.name}`; }; const alice = new Person('Alice'); // Key difference: console.log(Person.prototype); // Object with greet method console.log(alice.__proto__ === Person.prototype); // true console.log(Object.getPrototypeOf(alice) === Person.prototype); // true // Prototype chain: // alice → Person.prototype → Object.prototype → null // Inheritance example function Employee(name, title) { Person.call(this, name); this.title = title; } Employee.prototype = Object.create(Person.prototype); Employee.prototype.constructor = Employee; const bob = new Employee('Bob', 'Developer'); console.log(bob.greet()); // Inherited from Person // Modern ES6 equivalent class ModernEmployee extends Person { constructor(name, title) { super(name); this.title = title; } } // Best practices: // ✓ Use Object.getPrototypeOf() const proto = Object.getPrototypeOf(alice); // ✗ Don't modify Object.prototype Object.prototype.myMethod = function() {}; // BAD! // ✗ Don't use __proto__ directly (deprecated) // ✓ Use Object.setPrototypeOf() instead #JavaScript #WebDevelopment #Frontend #LearnInPublic #InterviewQuestions #Programming #TechInterviews
To view or add a comment, sign in
-
Day 49/50 – JavaScript Interview Question? Question: What is the difference between stopPropagation(), stopImmediatePropagation(), and preventDefault()? Simple Answer: stopPropagation() prevents event from bubbling/capturing to other elements. stopImmediatePropagation() also prevents other handlers on current element. preventDefault() cancels default browser action but doesn't stop propagation. 🧠 Why it matters in real projects: These control event behavior in complex UIs with nested elements. Misusing them causes bugs like forms not submitting, clicks triggering parent handlers, or custom behavior failing. Critical for proper event handling. 💡 One common mistake: Using stopPropagation() everywhere "to be safe" breaks event delegation patterns. Also confusing preventDefault() with stopping propagation—they serve different purposes. 📌 Bonus: // HTML: <div id="outer"><button id="inner">Click</button></div> const outer = document.getElementById('outer'); const inner = document.getElementById('inner'); // stopPropagation() - stops event flow inner.addEventListener('click', (e) => { console.log('Inner'); e.stopPropagation(); // Stops here! }); outer.addEventListener('click', () => { console.log('Outer'); // Won't fire }); // stopImmediatePropagation() - stops all handlers inner.addEventListener('click', (e) => { console.log('Handler 1'); e.stopImmediatePropagation(); }); inner.addEventListener('click', () => { console.log('Handler 2'); // Won't fire! }); // preventDefault() - cancels default action const link = document.querySelector('a'); link.addEventListener('click', (e) => { e.preventDefault(); // Link won't navigate // Event still propagates to parent! }); const form = document.querySelector('form'); form.addEventListener('submit', (e) => { e.preventDefault(); // Form won't submit handleAjaxSubmit(new FormData(form)); }); // Practical: Modal overlay modal.addEventListener('click', (e) => { e.stopPropagation(); // Clicks on modal don't close it }); overlay.addEventListener('click', () => { closeModal(); // Clicks on overlay close it }); // Best practice: Don't break delegation document.querySelector('.list').addEventListener('click', (e) => { if (e.target.matches('.item')) { // Don't use stopPropagation here! handleItemClick(e.target); } }); #JavaScript #WebDevelopment #Frontend #LearnInPublic #InterviewQuestions #Programming #TechInterviews #Events #EventPropagation #WebDev #DOM
To view or add a comment, sign in
-
Day 50/50 – JavaScript Interview Question? Question: What is the difference between setTimeout(), setImmediate(), and process.nextTick() in Node.js? Simple Answer: setTimeout() schedules callback in macrotask queue after delay. setImmediate() executes in next event loop iteration. process.nextTick() executes before next phase (microtask, highest priority). Order: nextTick() → Promises → setImmediate() → setTimeout(). 🧠 Why it matters in real projects: Understanding these is crucial for Node.js performance, avoiding event loop starvation, and controlling async execution order. Misusing them causes performance bottlenecks or unexpected behavior. 💡 One common mistake: Overusing process.nextTick() starves the event loop since it runs before I/O. Also assuming setImmediate() runs immediately—it's actually next iteration, and order with setTimeout(0) can vary. 📌 Bonus: console.log('1: Start'); setTimeout(() => console.log('2: setTimeout'), 0); setImmediate(() => console.log('3: setImmediate')); process.nextTick(() => console.log('4: nextTick')); Promise.resolve().then(() => console.log('5: Promise')); console.log('6: End'); // Output: // 1: Start // 6: End // 4: nextTick (highest priority) // 5: Promise (microtask) // 3: setImmediate (next loop) // 2: setTimeout (timer phase) // Use cases: // nextTick - let constructor complete class AsyncResource { constructor() { process.nextTick(() => this.init()); } } // setImmediate - break up long operations function processLargeArray(arr) { const chunk = arr.splice(0, 100); processChunk(chunk); if (arr.length > 0) { setImmediate(() => processLargeArray(arr)); // ✓ Yields } } // Danger: Recursive nextTick starves I/O! function dangerous() { process.nextTick(dangerous); // ✗ Infinite, blocks I/O } // Better: use setImmediate for recursion function better() { setImmediate(better); // ✓ Allows I/O } // Modern alternative to nextTick Promise.resolve().then(() => { // Microtask like nextTick, less aggressive }); 🎉 Series Complete! 50/50 JavaScript Interview Questions #JavaScript #WebDevelopment #Frontend #LearnInPublic #InterviewQuestions #Programming #TechInterviews #NodeJS #EventLoop #AsyncProgramming #WebDev #SeriesComplete
To view or add a comment, sign in
-
🚨 JavaScript Interview Trap: Shallow Copy vs Deep Copy Many developers think they understand object copying… Until this bug appears in production. 😅 You copy an object. You modify the copy. And suddenly… 💥 The original object also changes. Why does this happen? Because in JavaScript, objects are stored by reference. 🧠 Example JavaScript const user = { name: "Sajid", skills: ["JavaScript", "React"] }; const copy = { ...user }; copy.skills.push("Node.js"); console.log(user.skills); // ["JavaScript", "React", "Node.js"] Even though we copied the object… the original data changed. ⚠️ What Happened? This was a Shallow Copy. A shallow copy only duplicates the first level of an object. Nested objects or arrays still share the same memory reference. Think of it like: 📦 New box 📦 Same items inside Common Shallow Copy Methods These do NOT create deep copies: • Spread Operator { ...obj } • Object.assign() • Array.slice() • Array.from() They work great for flat objects. But for nested data, they can cause hidden bugs. 💡 Solution: Deep Copy To fully duplicate nested data: JavaScript const deepCopy = structuredClone(user); or JavaScript const deepCopy = JSON.parse(JSON.stringify(user)); Now changes won't affect the original object. ⚡ Small JavaScript concepts like this cause huge production bugs. Most developers learn syntax. Great developers understand how memory actually works. 💬 Quick question for you: Have you ever faced a Shallow Copy bug in a project? Comment "YES" or "NEVER AGAIN" 😄
To view or add a comment, sign in
-
Day 43/50 – JavaScript Interview Question? Question: What is Event Loop, Call Stack, and Task Queue in JavaScript? Simple Answer: The Call Stack tracks function execution (LIFO). The Task Queue (Callback Queue) holds callbacks from async operations. The Event Loop continuously checks if the Call Stack is empty, then moves tasks from the queue to the stack. Microtasks (Promises) have priority over Macrotasks (setTimeout). 🧠 Why it matters in real projects: Understanding the Event Loop is crucial for debugging async behavior, preventing UI blocking, and optimizing performance. It explains why promises execute before setTimeout(0), and helps you write non-blocking code in a single-threaded environment. 💡 One common mistake: Not understanding microtask vs macrotask priority, leading to unexpected execution order. Also, creating infinite microtask loops that starve the macrotask queue and freeze the UI. 📌 Bonus: // Example demonstrating execution order console.log('1: Sync Start'); setTimeout(() => { console.log('2: setTimeout (Macrotask)'); }, 0); Promise.resolve().then(() => { console.log('3: Promise 1 (Microtask)'); }).then(() => { console.log('4: Promise 2 (Microtask)'); }); console.log('5: Sync End'); // Output: // 1: Sync Start // 5: Sync End // 3: Promise 1 (Microtask) // 4: Promise 2 (Microtask) // 2: setTimeout (Macrotask) // Event Loop phases: // 1. Execute all synchronous code // 2. Execute all microtasks (Promises, queueMicrotask) // 3. Execute one macrotask (setTimeout, setInterval, I/O) // 4. Repeat // Call Stack visualization function first() { console.log('First'); second(); console.log('First again'); } function second() { console.log('Second'); third(); } function third() { console.log('Third'); } first(); // Stack: [first] → [first, second] → [first, second, third] // Output: First, Second, Third, First again // Microtask vs Macrotask setTimeout(() => console.log('Macro 1'), 0); Promise.resolve() .then(() => { console.log('Micro 1'); Promise.resolve().then(() => console.log('Micro 2')); }) .then(() => console.log('Micro 3')); setTimeout(() => console.log('Macro 2'), 0); // Output: Micro 1, Micro 2, Micro 3, Macro 1, Macro 2 // All microtasks complete before next macrotask! // Blocking the Event Loop (BAD!) function blockingOperation() { const start = Date.now(); while (Date.now() - start < 3000) { // Blocks for 3 seconds - UI freezes! } } // Better: Break into chunks async function nonBlockingOperation() { for (let i = 0; i < 1000; i++) { // Do work... if (i % 100 === 0) { await new Promise(resolve => setTimeout(resolve, 0)); // Yields to Event Loop every 100 iterations } } } // Microtask starvation (infinite loop) function starveEventLoop() { Promise.resolve().then(() => { starveEventLoop(); // Creates endless microtasks! // Macrotasks never run - UI freezes }); }
To view or add a comment, sign in
-
JavaScript Interview Question #2 ------------------------------------ Problem: Convert an array of key-value objects into a single object. Input: [{"key": "a", "value":1}, {"key": "b", "value": 2}] Output: {"a" : 1, "b" : 2} Solution: The input is an array of objects, and the goal is to transform it into a single object. There are multiple ways to solve this: 1. using for...of loop const arr = [{"key": "a", "value":1}, {"key": "b", "value": 2}]; let newObj = {}; for(let e of arr){ newObj[e.key] = e.value; } console.log(newObj); 2. using Object.fromEntries const arr = [{"key": "a", "value":1}, {"key": "b", "value": 2}]; const newObj = Object.fromEntries( arr.map(item => [item.key, item.value]) ); console.log(newObj); 3. using reduce() const arr = [{"key": "a", "value":1}, {"key": "b", "value": 2}]; const newObj = arr.reduce((acc, curr) => { acc[curr.key] = curr.value; return acc; }, {}); console.log(newObj); ------------------------------------------------------------------------------------- Different approaches help to build flexibility in problem-solving. I used the for...of loop in my interview. Which one do you prefer ?
To view or add a comment, sign in
-
Explore content categories
- Career
- Productivity
- Finance
- Soft Skills & Emotional Intelligence
- Project Management
- Education
- Technology
- Leadership
- Ecommerce
- User Experience
- Recruitment & HR
- Customer Experience
- Real Estate
- Marketing
- Sales
- Retail & Merchandising
- Science
- Supply Chain Management
- Future Of Work
- Consulting
- Writing
- Economics
- Artificial Intelligence
- Employee Experience
- Workplace Trends
- Fundraising
- Networking
- Corporate Social Responsibility
- Negotiation
- Communication
- Engineering
- Hospitality & Tourism
- Business Strategy
- Change Management
- Organizational Culture
- Design
- Innovation
- Event Planning
- Training & Development