JavaScript & jQuery Interview Questions

⚑ JavaScript Fundamentals

1. What is JavaScript and what are its key features?
JavaScript is a high-level, interpreted programming language primarily used for web development to create interactive and dynamic web pages. It's a multi-paradigm language supporting object-oriented, imperative, and functional programming styles. Key features include dynamic typing, prototype-based inheritance, first-class functions, event-driven programming, and asynchronous capabilities. JavaScript runs in browsers and on servers (Node.js), making it versatile for full-stack development. It's single-threaded but uses the event loop for non-blocking operations.
2. What is the difference between var, let, and const?
Var has function scope or global scope, is hoisted with undefined initialization, and can be redeclared. Let has block scope, is hoisted but not initialized (temporal dead zone), cannot be redeclared in the same scope, and is preferred for variables that change. Const has block scope, must be initialized at declaration, cannot be reassigned (but object properties can change), and is used for constants. Modern JavaScript prefers const by default, let when reassignment is needed, and avoids var to prevent scope-related bugs.
3. What is hoisting in JavaScript?
Hoisting is JavaScript's behavior of moving variable and function declarations to the top of their scope during compilation phase before execution. Function declarations are fully hoisted with their definitions, so they can be called before declaration. Var variables are hoisted but initialized as undefined. Let and const are hoisted but not initialized, creating a temporal dead zone until declaration is reached. Class declarations are hoisted but not initialized. Understanding hoisting helps avoid unexpected behavior and write cleaner code.
4. Explain closures in JavaScript.
A closure is a function that has access to variables from its outer (enclosing) function's scope, even after the outer function has returned. Closures are created every time a function is created, capturing the lexical environment. They enable data privacy, creating private variables and methods, and are fundamental to patterns like module pattern and callbacks. Closures maintain references to outer variables, which can cause memory leaks if not managed properly. They're extensively used in event handlers, callbacks, and functional programming.
5. What is the difference between == and === operators?
The == operator performs type coercion before comparison, converting operands to the same type, which can lead to unexpected results like "5" == 5 being true. The === operator (strict equality) checks both value and type without coercion, so "5" === 5 is false. Similarly, != allows type coercion while !== is strict. Best practice is to always use === and !== to avoid bugs from implicit type conversion. The == operator follows complex coercion rules that can be confusing and error-prone.
6. What are data types in JavaScript?
JavaScript has seven primitive types: Number (integers and floats), String (text), Boolean (true/false), Undefined (declared but not assigned), Null (intentional absence), Symbol (unique identifiers), and BigInt (large integers). Everything else is an Object type, including arrays, functions, and dates. Primitives are immutable and stored by value, while objects are mutable and stored by reference. Use typeof operator to check types, though it has quirks like typeof null returning "object". Understanding types is crucial for avoiding common bugs.
7. What is the difference between null and undefined?
Undefined means a variable has been declared but not assigned a value, or a function doesn't return anything. Null is an assignment value representing intentional absence or empty value. Undefined is the default state, while null must be explicitly assigned. Both are falsy values but typeof undefined returns "undefined" while typeof null returns "object" (historical bug). Use undefined for uninitialized variables and null for intentionally empty values. They're loosely equal (null == undefined) but not strictly equal (null !== undefined).
8. What is the 'this' keyword in JavaScript?
The 'this' keyword refers to the context in which a function is executed, not where it's defined. In global context, 'this' refers to the window object (strict mode: undefined). In object methods, 'this' refers to the object. In constructors and classes, 'this' refers to the newly created instance. Arrow functions don't have their own 'this', inheriting from parent scope. Use call(), apply(), or bind() to explicitly set 'this'. Understanding 'this' is crucial for object-oriented programming and avoiding common pitfalls.
9. What are arrow functions and how do they differ from regular functions?
Arrow functions provide concise syntax using => and have lexical 'this' binding, inheriting from surrounding scope. They don't have their own 'this', 'arguments', 'super', or 'new.target'. Arrow functions cannot be used as constructors and don't have prototype property. They're ideal for callbacks and functional programming but not suitable for object methods needing dynamic 'this'. Implicit return works for single expressions without braces. Regular functions have dynamic 'this' based on call context and support all function features.
10. What is event bubbling and event capturing?
Event bubbling is the propagation of events from the target element up through parent elements to the document root. Event capturing (trickling) is the opposite, flowing from root down to target element. Events have three phases: capturing (root to target), target (event reaches target), and bubbling (target to root). By default, event listeners execute in bubbling phase. Use addEventListener's third parameter (true) for capturing phase. Use event.stopPropagation() to prevent further propagation. Understanding these helps manage event delegation and prevent unwanted event handling.

πŸ”₯ Advanced JavaScript Concepts

11. What is the Event Loop in JavaScript?
The Event Loop is JavaScript's concurrency model that handles asynchronous operations despite being single-threaded. It continuously checks the call stack and task queues. Synchronous code executes on the call stack. Asynchronous callbacks go to the task queue (macrotasks) or microtask queue (promises). When the stack is empty, the event loop processes microtasks first, then macrotasks. This enables non-blocking I/O operations. Understanding the event loop helps write efficient async code and debug timing-related issues.
12. What are Promises in JavaScript?
Promises represent the eventual completion or failure of an asynchronous operation, providing a cleaner alternative to callbacks. A promise has three states: pending (initial), fulfilled (success), or rejected (failure). Use .then() for success, .catch() for errors, and .finally() for cleanup. Promises chain multiple async operations avoiding callback hell. Promise.all() waits for all promises, Promise.race() resolves with the first, Promise.allSettled() waits for all regardless of result. Async/await syntax makes promise-based code look synchronous, improving readability.
13. What is async/await and how does it work?
Async/await is syntactic sugar over promises, making asynchronous code look synchronous and more readable. The async keyword marks functions returning promises implicitly. The await keyword pauses execution until the promise resolves, only working inside async functions. It simplifies error handling with try/catch blocks instead of .catch() chains. Await expressions return resolved values or throw rejected values. Multiple awaits execute sequentially; use Promise.all() for parallel execution. Async/await doesn't change JavaScript's asynchronous nature, just provides cleaner syntax.
14. What is the difference between call(), apply(), and bind()?
Call(), apply(), and bind() explicitly set the 'this' value in functions. Call() invokes the function immediately with individual arguments: func.call(thisArg, arg1, arg2). Apply() invokes immediately with arguments as an array: func.apply(thisArg, [args]). Bind() returns a new function with 'this' permanently bound without invoking: const boundFunc = func.bind(thisArg). Use call/apply for immediate invocation, bind for later execution or partial application. Call is preferred when you know arguments, apply when you have an array of arguments.
15. What is prototype and prototypal inheritance?
Every JavaScript object has a prototype, an object from which it inherits properties and methods. Prototypal inheritance allows objects to inherit directly from other objects without classes (though ES6 classes use prototypes internally). The prototype chain is traversed when accessing properties: if not found on object, JavaScript checks its prototype, then prototype's prototype, until reaching null. Use Object.create() for pure prototypal inheritance or constructor functions/classes for more traditional patterns. Understanding prototypes is essential for JavaScript's inheritance model and optimization.
16. What are higher-order functions?
Higher-order functions are functions that take other functions as arguments or return functions, enabling functional programming patterns. Common examples include map(), filter(), reduce(), forEach(), and sort(). They abstract common patterns, promote code reuse, and enable composition. Higher-order functions treat functions as first-class citizens, allowing them to be stored in variables, passed around, and returned. They're fundamental to callbacks, event handlers, and decorators. Understanding higher-order functions improves code expressiveness and enables functional programming techniques.
17. What is the difference between map(), filter(), and reduce()?
Map() transforms each array element and returns a new array of the same length with transformed values. Filter() creates a new array with elements passing a test condition, potentially having fewer elements. Reduce() accumulates array elements into a single value using an accumulator and current value. Map is for transformation, filter for selection, reduce for aggregation. All three don't mutate the original array. They're chainable for complex data transformations. Use map for one-to-one transformations, filter for conditional selection, reduce for calculating totals or complex accumulations.
18. What is debouncing and throttling?
Debouncing delays function execution until after a specified time has passed since the last call, ideal for search inputs where you wait for user to stop typing. Throttling limits function execution to once per specified interval, regardless of how many times it's called, ideal for scroll or resize events. Debouncing cancels previous pending executions, while throttling guarantees regular intervals. Both improve performance by reducing function calls. Debouncing waits for inactivity, throttling maintains maximum frequency. Use libraries like Lodash or implement custom solutions for these patterns.
19. What are generators in JavaScript?
Generators are functions that can pause and resume execution using function* syntax and yield keyword. They return an iterator object with next() method that returns {value, done} objects. Generators maintain state between yields, enabling lazy evaluation and infinite sequences. They simplify async flows and custom iterators. Use yield* to delegate to another generator. Generators support bidirectional communication by passing values to next(). They're useful for state machines, custom iteration, and async control flow (though async/await is now preferred for async operations).
20. What is the Spread operator and Rest parameters?
The spread operator (...) expands iterables into individual elements, used for array/object copying, merging, and function arguments. Rest parameters (...args) collect multiple elements into an array, used in function parameters to handle variable arguments. Spread expands, rest collects. Spread creates shallow copies, requiring deep copy techniques for nested objects. Rest parameters replace the arguments object with a real array. Both use the same syntax (...) but in different contexts. They simplify array manipulation, object merging, and function parameter handling.

🎯 DOM Manipulation & Events

21. What is the DOM (Document Object Model)?
The DOM is a programming interface representing HTML/XML documents as a tree structure of nodes, where each node represents part of the document. It allows JavaScript to access, modify, add, or delete elements and attributes dynamically. The DOM is language-independent but commonly accessed via JavaScript. The tree structure has a root (document), with parent-child-sibling relationships. DOM manipulation is essential for creating interactive web applications. Modern frameworks abstract DOM manipulation, but understanding it is crucial for performance optimization and debugging.
22. What is the difference between innerHTML, textContent, and innerText?
InnerHTML gets/sets HTML content including tags, parsing HTML and executing scripts, which can pose security risks (XSS). TextContent gets/sets only text content, stripping HTML tags, faster than innerText, and returns all text including hidden elements. InnerText returns visible text only, respecting CSS styling, but is slower due to layout calculations. Use textContent for better performance and security when dealing with plain text. Use innerHTML only when you need to insert HTML and trust the source. InnerText is rarely needed unless visibility matters.
23. What is event delegation?
Event delegation attaches a single event listener to a parent element to handle events for multiple child elements, leveraging event bubbling. The handler checks the event.target to determine which child triggered the event. Benefits include better performance (fewer listeners), handling dynamically added elements, and reduced memory usage. Use event.target for the clicked element and event.currentTarget for the element with the listener. Event delegation is ideal for lists, tables, or any scenario with many similar elements. It's a fundamental pattern for efficient event handling.
24. What is the difference between preventDefault() and stopPropagation()?
PreventDefault() stops the browser's default action for an event, like preventing form submission, link navigation, or checkbox toggling. StopPropagation() prevents the event from bubbling up or capturing down the DOM tree, stopping parent handlers from executing. They're independent and can be used together. Use preventDefault() to control browser behavior while allowing parent handlers to run. Use stopPropagation() when you want to isolate event handling to specific elements. StopImmediatePropagation() also prevents other handlers on the same element from executing.
25. How do you create and remove DOM elements?
Create elements with document.createElement('tagName'), set properties/content, and append with appendChild() or append(). Use insertBefore() for specific positioning or insertAdjacentHTML() for HTML strings. Remove elements with element.remove(), parentElement.removeChild(element), or by setting innerHTML. Clone elements with cloneNode(deep). Modern methods include append(), prepend(), after(), before(), and replaceWith(). Always consider memory leaks by removing event listeners before removal. Creating document fragments for multiple elements improves performance by minimizing reflows.

πŸ’» ES6+ Features

26. What are template literals?
Template literals use backticks (`) for strings, supporting multi-line strings without escape characters and string interpolation with ${expression} syntax. They're more readable than concatenation and support embedded expressions, function calls, and complex logic. Tagged templates enable custom string processing with template tag functions. Template literals preserve whitespace and line breaks, useful for HTML templates or formatted text. They support nesting and can include any JavaScript expression. They've become the standard for string handling in modern JavaScript, replacing traditional quotes in many scenarios.
27. What is destructuring in JavaScript?
Destructuring extracts values from arrays or properties from objects into distinct variables using concise syntax. Array destructuring uses square brackets: const [a, b] = array. Object destructuring uses curly braces: const {name, age} = object. It supports default values, nested destructuring, rest patterns, and renaming. Destructuring works in function parameters, enabling clean parameter handling. It simplifies assignments and improves readability. Swapping variables becomes trivial: [a, b] = [b, a]. Destructuring is fundamental to modern JavaScript, widely used in function parameters and imports.
28. What are ES6 Classes?
ES6 classes provide syntactic sugar over JavaScript's prototypal inheritance, offering cleaner syntax for object-oriented programming. Classes use constructor() for initialization, support inheritance with extends, and super for calling parent methods. Methods are added to prototype automatically. Classes support static methods (class-level), getters/setters, and private fields (#fieldName). Class declarations aren't hoisted and always run in strict mode. Despite class syntax, JavaScript remains prototype-based. Classes improve code organization and readability while maintaining JavaScript's flexibility. They're the preferred way to create reusable object types.
29. What are Modules in JavaScript (import/export)?
ES6 modules enable code organization into reusable pieces with explicit dependencies using import and export. Named exports allow multiple exports per file: export const name; imported with import {name}. Default exports allow one main export: export default function; imported without braces. Modules have their own scope, preventing global pollution. They enable tree-shaking for optimization. Use type="module" in script tags for browser support. Modules are automatically in strict mode. They support dynamic imports with import() function for code splitting. Modules are essential for modern JavaScript application architecture.
30. What is the difference between Set and Array?
Set is a collection of unique values, automatically removing duplicates, while arrays allow duplicate values. Sets use has() for O(1) lookups versus indexOf() O(n) in arrays. Sets have add(), delete(), and clear() methods versus array's push(), splice(), etc. Sets maintain insertion order and iterate with forEach(), for...of, or spread operator. Use Sets for unique value collections, membership tests, or removing duplicates from arrays. Arrays provide indexed access and more built-in methods. Convert between them easily: new Set(array) or [...set]. Sets are optimized for uniqueness checks.

🌐 Asynchronous JavaScript

31. What is callback hell and how do you avoid it?
Callback hell (pyramid of doom) occurs when multiple nested callbacks make code hard to read and maintain. It happens with deeply nested asynchronous operations creating rightward drift. Avoid it by using Promises for better chaining, async/await for synchronous-looking code, named functions instead of anonymous callbacks, or modularizing code into smaller functions. Modern JavaScript strongly favors Promises and async/await over callbacks. Good error handling and proper code organization also help. Callback hell was a major pain point that Promises were designed to solve.
32. What is the difference between synchronous and asynchronous code?
Synchronous code executes sequentially, blocking subsequent operations until completion, making it simple but potentially inefficient for I/O operations. Asynchronous code initiates operations and continues executing without waiting, using callbacks, promises, or async/await to handle completion. JavaScript is single-threaded but achieves async behavior through the event loop and Web APIs. Async code is non-blocking, improving responsiveness and throughput, essential for network requests, timers, and file operations. Understanding when to use each is crucial for building responsive applications without blocking the UI thread.
33. What are Web APIs in the browser?
Web APIs are browser-provided interfaces for features beyond JavaScript language specification, including DOM manipulation, AJAX (fetch/XMLHttpRequest), timers (setTimeout/setInterval), Web Storage (localStorage/sessionStorage), Geolocation, Canvas, WebSockets, and more. They're not part of JavaScript itself but available in browser environments. Web APIs handle I/O operations asynchronously, delegating to browser/OS while JavaScript continues executing. They return to JavaScript through callbacks or promises. Understanding Web APIs is essential for browser programming. Node.js provides different APIs for server-side operations.
34. What is AJAX and how does it work?
AJAX (Asynchronous JavaScript and XML) enables loading data from servers asynchronously without page refresh, creating dynamic, responsive web applications. Modern implementations use fetch API or axios library instead of XMLHttpRequest. AJAX requests are asynchronous, handled by browser Web APIs. Common operations include GET (retrieve data), POST (send data), PUT (update), and DELETE. AJAX revolutionized web development, enabling single-page applications. Handle responses with promises or async/await. Consider error handling, loading states, and CORS restrictions. Despite the name, JSON has largely replaced XML.
35. What is the Fetch API?
Fetch API is the modern standard for making HTTP requests, replacing XMLHttpRequest with a promise-based interface. Basic syntax: fetch(url).then(response => response.json()).then(data => ...). Fetch returns promises, supporting async/await syntax. It provides cleaner error handling and more powerful features. Note: fetch only rejects on network errors, not HTTP error statuses (404, 500), requiring response.ok checks. Configure requests with options object for method, headers, body, etc. Fetch supports streaming responses and request/response objects with extensive properties. It's now the preferred way to make HTTP requests.

πŸ›‘οΈ Error Handling & Best Practices

36. How do you handle errors in JavaScript?
Use try-catch blocks for synchronous code and errors that might be thrown. For promises, use .catch() or try-catch with async/await. Throw custom errors with throw new Error(message). Implement global error handlers with window.onerror for uncaught errors. Use .finally() for cleanup code that runs regardless of success/failure. Create custom error classes extending Error for specific error types. Always handle promise rejections to avoid unhandled promise rejection warnings. Proper error handling improves user experience and makes debugging easier. Log errors appropriately for monitoring and debugging.
37. What is strict mode in JavaScript?
Strict mode, enabled with "use strict", makes JavaScript throw errors for previously silent mistakes, improving code quality and security. It prevents use of undeclared variables, disallows duplicate parameter names, makes 'this' undefined in global context, prohibits octal syntax, and prevents deletion of undeletable properties. Strict mode applies to entire scripts or individual functions. ES6 modules and classes are automatically in strict mode. It helps catch common coding mistakes and makes code more secure. Modern development should always use strict mode for better error detection and optimization opportunities.
38. What is the difference between deep copy and shallow copy?
Shallow copy creates a new object copying only the first level, with nested objects remaining references to originals. Deep copy creates a completely independent copy with all nested objects cloned. Spread operator and Object.assign() create shallow copies. For deep copies, use JSON.parse(JSON.stringify(obj)) for simple objects (loses functions, dates, undefined), structuredClone() (modern browsers), or libraries like Lodash's cloneDeep(). Shallow copies are faster and sufficient when no nested objects exist. Deep copies prevent unintended mutations but are more expensive. Choose based on data structure and mutation requirements.
39. What is memoization in JavaScript?
Memoization is an optimization technique caching function results based on arguments, avoiding expensive recalculations for repeated calls with same inputs. Implement by storing results in an object/Map keyed by arguments. Useful for recursive functions (Fibonacci), expensive calculations, or API calls. Memoization trades memory for speed. Clear caches when needed to prevent memory issues. Libraries like Lodash provide memoize functions. Consider memoization for pure functions (same input always returns same output) with expensive operations. It's a common optimization in dynamic programming and React (useMemo, React.memo).
40. What are JavaScript design patterns you should know?
Module pattern encapsulates code using closures for privacy. Singleton ensures one instance. Factory creates objects without specifying exact class. Observer (pub-sub) manages dependencies between objects for event handling. Prototype uses prototypal inheritance for object creation. Constructor pattern creates objects with new keyword. Revealing Module exposes public API while keeping internals private. Decorator adds functionality without modifying original. Design patterns provide proven solutions to common problems, improve code organization and maintainability. Modern JavaScript uses modules natively, but understanding patterns improves architectural decisions.

πŸ”§ Advanced Topics

41. What is currying in JavaScript?
Currying transforms a function taking multiple arguments into a sequence of functions each taking a single argument. Example: add(a, b) becomes add(a)(b). Currying enables partial application, creating specialized functions from general ones. It's useful for function composition and creating reusable utilities. Implement manually with nested functions or use libraries like Lodash. Currying makes code more modular and testable. It's fundamental to functional programming. While not as common as in purely functional languages, currying is valuable for certain patterns in JavaScript, especially with higher-order functions.
42. What is the difference between Object.freeze(), Object.seal(), and Object.preventExtensions()?
Object.freeze() makes object completely immutable: no adding, removing, or modifying properties (shallow freeze only). Object.seal() prevents adding/removing properties but allows modifying existing ones. Object.preventExtensions() only prevents adding new properties, allowing modification and deletion of existing ones. Check with Object.isFrozen(), Object.isSealed(), Object.isExtensible(). All three are shallow operations, not affecting nested objects. Use freeze for constants, seal for fixed structure with mutable values, preventExtensions for controlling object shape. Strict mode throws errors when violations occur, otherwise operations fail silently.
43. What are Symbols in JavaScript?
Symbols are unique, immutable primitive values used as object property keys, guaranteed never to collide with string keys. Created with Symbol(description), each call produces a unique symbol. Symbols are not enumerable in for...in or Object.keys(), providing hidden properties. Well-known symbols like Symbol.iterator define language behaviors. Symbol.for(key) creates global registry symbols for cross-realm sharing. Use symbols for meta-properties, private object state, or custom iteration. They're useful for adding properties without name conflicts. Symbols enable protocol implementation without risking property name collisions.
44. What is the Proxy object in JavaScript?
Proxy creates a wrapper around an object to intercept and customize fundamental operations like property access, assignment, deletion, and function invocation using handler traps. Common traps include get, set, has, deleteProperty, apply. Proxies enable validation, logging, computed properties, and virtual objects. They're used in frameworks for reactivity (Vue 3). Revocable proxies can be disabled. Proxies are powerful for meta-programming but add performance overhead. They enable creating objects with custom behavior without modifying original objects, useful for implementing observables, access control, or data validation.
45. What is WeakMap and WeakSet?
WeakMap is a collection of key-value pairs where keys must be objects and are held weakly, allowing garbage collection if no other references exist. WeakMap doesn't prevent keys from being garbage collected, useful for associating metadata with objects without memory leaks. It has only get(), set(), has(), delete() methodsβ€”no iteration or size property. WeakSet is similar but stores only objects, not key-value pairs. Use WeakMap for private data, caching based on objects, or DOM node metadata. WeakSet is useful for tracking object membership without preventing cleanup.
46. What is the difference between localStorage, sessionStorage, and cookies?
LocalStorage persists data permanently (unless cleared), has ~5-10MB storage, accessible only in browser, and never sent to server. SessionStorage persists for tab/window session, cleared when closed, with similar storage capacity. Cookies have ~4KB limit, persist based on expiration date, sent with every HTTP request, and accessible server-side. Use localStorage for long-term client-side data, sessionStorage for temporary tab-specific data, cookies for server communication or authentication tokens. All are origin-specific. LocalStorage and sessionStorage use simple key-value API, while cookies require string parsing and have complex attributes.
47. What is JSON and how do you parse/stringify it?
JSON (JavaScript Object Notation) is a lightweight, text-based data format for data exchange, using JavaScript object syntax. JSON.parse() converts JSON strings to JavaScript objects, throwing errors for invalid JSON. JSON.stringify() converts JavaScript objects to JSON strings, with optional replacer function and space parameter for formatting. JSON supports objects, arrays, strings, numbers, booleans, and null but not functions, undefined, symbols, or dates (converted to strings). Use try-catch for parsing untrusted JSON. Both methods support revivers/replacers for custom transformation during conversion. JSON is language-independent and ubiquitous for APIs.
48. What is the difference between for...in and for...of loops?
For...in iterates over enumerable property names (keys) of objects, including inherited properties from prototype chain, mainly for objects not arrays. For...of iterates over iterable values (array elements, string characters, Map/Set values) using the iterator protocol, working with any iterable. For...in returns indices for arrays (as strings), while for...of returns actual values. Use for...of for arrays, strings, Maps, Sets; use for...in for object properties. For...of is more predictable and works with break/continue. Array.forEach() is another alternative specifically for arrays.
49. What are tagged template literals?
Tagged templates are functions processing template literals, receiving an array of string parts and interpolated values separately. The tag function gets called with (strings, ...values) arguments. This enables custom string processing, escaping, internationalization, or creating DSLs. Example: sql`SELECT * FROM users WHERE id = ${id}` could create safe parameterized queries. Tagged templates preserve raw string information (backslashes) via strings.raw property. They're powerful for creating libraries with clean syntax. Common uses include styled-components, HTML sanitization, or GraphQL queries. They combine readability with programmability.
50. What are the differences between ES5 and ES6 (ES2015)?
ES6 introduced major improvements: let/const for block scope, arrow functions, classes, template literals, destructuring, spread/rest operators, default parameters, Promises, modules (import/export), Map/Set, Symbol, for...of loops, generators, and enhanced object literals. ES6 modernized JavaScript with better syntax, improved scoping, native module system, and powerful new features. It established yearly release cycle (ES2015, ES2016, etc.). Modern browsers support most ES6+ features; transpilers like Babel enable using new features while supporting older browsers. ES6 fundamentally changed JavaScript development, making it more powerful and expressive.

πŸ’™ jQuery Fundamentals

51. What is jQuery and why was it popular?
jQuery is a fast, lightweight JavaScript library simplifying HTML document traversal, manipulation, event handling, animation, and AJAX. Created in 2006, it provided consistent API across browsers, solving cross-browser compatibility issues that plagued early web development. jQuery's selector engine (Sizzle) made DOM selection intuitive. Its concise syntax ($ function) enabled chaining for readable code. jQuery made JavaScript accessible to developers unfamiliar with vanilla JS complexities. While modern JavaScript and frameworks have reduced jQuery's necessity, it remains in many legacy applications and taught developers patterns still used today.
52. What is the $ symbol in jQuery?
The $ is an alias for the jQuery object, the core function providing access to all jQuery functionality. $() selects DOM elements using CSS selectors, creates elements from HTML strings, or wraps DOM elements. It returns jQuery objects (collections) with jQuery methods. Use jQuery.noConflict() if $ conflicts with other libraries, then use jQuery instead. $(document).ready() ensures DOM is loaded before code execution. The $ symbol made jQuery famous for concise syntax. While $ is just a variable name, it became iconic for jQuery and influenced other libraries.
53. What is the difference between $(document).ready() and window.onload?
$(document).ready() fires when DOM is fully loaded and parsed, before images and stylesheets finish loading, allowing early manipulation. Window.onload waits for everything (images, stylesheets, frames) to load completely, taking longer. $(document).ready() can have multiple handlers; window.onload gets overwritten by subsequent assignments. Use $(document).ready() for DOM manipulation requiring structure but not resources. Modern vanilla JavaScript uses DOMContentLoaded event (similar to ready) or defer/async script attributes. jQuery's ready became so common it influenced how developers think about page loading.
54. How do you select elements in jQuery?
jQuery uses CSS selectors with $() function: $('#id') for IDs, $('.class') for classes, $('element') for tags, $('[attribute]') for attributes. Combine selectors: $('div.class'), use hierarchical selectors: $('parent > child'), or pseudo-selectors: $(':first', ':visible', ':checked'). jQuery adds custom selectors like :eq(), :gt(), :lt(). Chaining is powerful: $('div').find('.inner').addClass('active'). jQuery selector engine (Sizzle) normalized behavior across browsers. Modern querySelectorAll() provides similar functionality natively. Understanding jQuery selectors helps with modern frameworks and vanilla JS selectors.
55. What is method chaining in jQuery?
Method chaining allows calling multiple jQuery methods on the same selection in one statement, as most methods return the jQuery object. Example: $('div').addClass('active').fadeIn().css('color', 'red'). Chaining improves readability and reduces code. Use .end() to return to previous selection in chain. Methods modifying selections (filter, find) change what's chained. Chaining reduces repeated selections, improving performance slightly. It's a fluent API pattern jQuery popularized, now common in many libraries. While powerful, overly long chains can hurt readability; break complex chains for clarity.
56. What are jQuery selectors vs JavaScript selectors?
jQuery selectors ($()) return jQuery objects with jQuery methods, while native selectors (querySelector, querySelectorAll) return NodeLists or Elements. jQuery normalizes behavior across browsers (historically important) and provides additional methods. jQuery objects are array-like collections; access raw DOM with [0] or .get(0). Modern JavaScript querySelector/querySelectorAll support same CSS selectors jQuery does. jQuery selectors are sometimes slower but more feature-rich. Converting: $(nativeElement) wraps in jQuery; jQueryObject[0] gets native element. Modern development often prefers native selectors for performance and avoiding jQuery dependency.
57. How do you manipulate CSS in jQuery?
jQuery provides .css() to get/set CSS properties: .css('color', 'red') or .css({color: 'red', fontSize: '14px'}). Use .addClass(), .removeClass(), .toggleClass() for class manipulation. .hasClass() checks class existence. .show()/.hide() control visibility. .width(), .height(), .position(), .offset() handle dimensions and positioning. jQuery normalizes CSS property names (use camelCase or hyphenated). Prefer classes over direct CSS for separation of concerns. Modern JavaScript uses classList and style property similarly. CSS manipulation was jQuery's strength in handling browser inconsistencies.
58. What is the difference between .html(), .text(), and .val() in jQuery?
.html() gets/sets HTML content including tags, similar to innerHTML, parsing HTML and executing scripts (XSS risk with untrusted content). .text() gets/sets text content only, stripping HTML tags, safer than .html() for user input, similar to textContent. .val() gets/sets form element values (input, select, textarea), handling form data. Use .html() for trusted HTML content, .text() for plain text to prevent XSS, .val() for form operations. Without arguments, they get content; with arguments, they set content. These methods work on jQuery collections, affecting all matched elements.
59. How do you handle events in jQuery?
jQuery simplifies event handling with .on() method: $('.button').on('click', function(){}). Use .off() to remove handlers. Shorthand methods exist: .click(), .hover(), .focus(), etc. Event delegation: $('parent').on('click', 'selector', handler) handles current and future elements. Access event object for event.target, event.preventDefault(), event.stopPropagation(). .one() fires handler once then removes it. jQuery normalizes events across browsers. .trigger() programmatically fires events. Modern JavaScript addEventListener works similarly, but jQuery made event handling much simpler in early web development.
60. What is event delegation in jQuery?
Event delegation attaches event listeners to parent elements that handle events for child elements through event bubbling, even for dynamically added elements. Syntax: $('parent').on('event', 'child-selector', handler). Benefits include better performance (fewer listeners), handling future elements automatically, and reduced memory. The handler checks if event.target matches the selector. Delegation works because events bubble up the DOM. It's essential for dynamic content. jQuery made delegation straightforward with .on() syntax. This pattern is fundamental to efficient event handling in both jQuery and vanilla JavaScript applications.

🎨 jQuery Effects & Animation

61. What are jQuery effects methods?
jQuery provides built-in animation methods: .show()/.hide() control visibility, .fadeIn()/.fadeOut()/.fadeTo() animate opacity, .slideUp()/.slideDown()/.slideToggle() animate height. All accept duration (milliseconds or 'slow'/'fast') and callback. .toggle() toggles visibility. .animate() creates custom animations on numeric CSS properties. .stop() stops animations, .delay() adds pauses. .finish() completes animations immediately. Effects queue automatically; use queue:false for simultaneous animations. jQuery effects simplified animations before CSS transitions existed. Modern development prefers CSS animations for better performance, but jQuery effects remain useful for complex JavaScript-driven animations.
62. How do you create custom animations in jQuery?
Use .animate() with an object of CSS properties and values: $('.box').animate({width: '200px', opacity: 0.5}, 1000). Animate numeric CSS properties (not colors without plugins). Chain animations for sequences. Provide callback for completion logic. Options include duration, easing ('swing' or 'linear'), complete callback, and step function. Use += or -= for relative values. Queue animations by chaining or control with {queue: false} for simultaneity. Stop animations with .stop(). Animate accepts second parameter for options object. While powerful, CSS animations and transitions are now preferred for performance.
63. What is animation queue in jQuery?
jQuery queues animations on elements by default, executing them sequentially in order they're called. Each element has its own queue. Use .queue() to manipulate, view, or add custom functions. .dequeue() starts next animation. .clearQueue() empties queue. .stop() stops current animation, optionally clearing queue and jumping to end. Animations queue automatically; use {queue: false} in .animate() for simultaneous effects. Understanding queues prevents unexpected animation behavior. Queue system ensures animations don't conflict. Modern JavaScript often uses Promises or async/await for sequencing, but jQuery's queue was innovative for its time.
64. What is the difference between .stop() and .finish()?
.stop() stops currently running animation at current position, with optional parameters: .stop(clearQueue, jumpToEnd). Without parameters, stops current, allows queued animations. .stop(true) clears queue. .stop(true, true) clears queue and jumps to end state. .finish() stops all animations, clears queue, and immediately completes all queued animations, setting properties to their target values. Use .stop() before new animations to prevent queuing issues. .finish() is useful for reset operations. Understanding these prevents animation artifacts and timing issues when users rapidly interact with animated elements.
65. How do you add delays to animations in jQuery?
Use .delay(milliseconds) to pause between animations in a queue: $('.box').fadeIn().delay(1000).fadeOut(). Delay only affects queued jQuery effects, not custom code. For delayed code execution, use setTimeout(). Delay accepts queue name as second parameter. It's chainable like other jQuery methods. For complex timing, consider promises or async/await. Delay is simple for basic animation sequencing but limited compared to modern timing controls. CSS animation-delay is now often preferred. Combine with callbacks for complex timing: .animate({}, duration, callback). Understanding queuing is essential for effective delay usage.

🌐 jQuery AJAX

66. How do you make AJAX requests with jQuery?
jQuery simplifies AJAX with $.ajax() (full control) and shortcuts: $.get(), $.post(), $.getJSON(). Example: $.ajax({url: '/api', method: 'POST', data: {}, success: function(data){}, error: function(){}}). $.ajax() returns jqXHR object (jQuery's XMLHttpRequest) with promise interface. Shortcuts are more concise: $.get('/api', function(data){}). jQuery handles JSON parsing automatically. Set global defaults with $.ajaxSetup(). jQuery normalized AJAX across browsers when this was painful. Modern fetch() API or axios are now preferred, but jQuery AJAX remains in legacy code and is still simpler for basic requests.
67. What is the difference between $.ajax(), $.get(), and $.post()?
$.ajax() provides full control with extensive options: method, headers, data, timeout, callbacks, dataType, etc. $.get() is shorthand for GET requests with simpler syntax: $.get(url, data, callback, dataType). $.post() is shorthand for POST requests with similar simplified syntax. Shortcuts are more readable for simple requests; use $.ajax() for complex scenarios requiring custom headers, error handling, or advanced options. All return jqXHR objects with promise methods (.done(), .fail(), .always()). Shortcuts internally call $.ajax(). Choose based on complexity needs: shortcuts for simple, $.ajax() for advanced control.
68. How do you handle errors in jQuery AJAX?
Use error callback in $.ajax({error: function(jqXHR, status, error){}}), or .fail() on returned jqXHR: $.ajax().fail(function(){}). jqXHR provides status codes, responseText, statusText. .done() handles success, .fail() handles errors, .always() runs regardless. Use try-catch for JSON parsing errors. Global error handling: $(document).ajaxError(). Check jqXHR.status for HTTP codes. Consider timeouts and network errors separately. Modern promises and async/await provide cleaner error handling, but jQuery's callbacks work well. Always implement error handling for production AJAX; don't assume success.
69. What are jQuery AJAX global events?
Global AJAX events allow monitoring all AJAX requests: .ajaxStart() fires when first request begins, .ajaxStop() when all complete, .ajaxSend() before each request, .ajaxSuccess()/.ajaxError() for each success/error, .ajaxComplete() for each completion. Attach to document: $(document).ajaxStart(showLoader). Useful for loading indicators, global error handling, or request logging. Disable for specific requests with {global: false}. Global events simplified common patterns like loading spinners. Modern applications often use interceptors (axios) or service workers, but jQuery's approach was pioneering and still useful in jQuery-based applications.
70. What is .load() method in jQuery?
.load() loads HTML from server and inserts into matched elements: $('#result').load('/page.html'). It combines AJAX GET request with DOM insertion. Optionally filter loaded content: .load('/page.html #content') loads only #content. Provide callback: .load(url, callback(responseText, status, xhr)). .load() submits POST if data object provided. It's convenient for loading partial views or updating page sections. Modern approaches use fetch() with innerHTML or frameworks with component loading. .load() was popular for creating dynamic single-page-like experiences. Still useful for simple content loading without full framework overhead.

πŸ”§ jQuery Utilities & Advanced

71. What are jQuery utility methods?
jQuery provides utilities beyond DOM manipulation: $.each() iterates arrays/objects, $.map() transforms arrays, $.grep() filters arrays, $.merge() combines arrays, $.extend() deep/shallow copies objects, $.trim() removes whitespace, $.isArray(), $.isFunction(), $.isNumeric() for type checking, $.parseJSON(), $.parseHTML() for parsing. These work on plain JavaScript data, not requiring jQuery objects. Use $.ajax(), $.param() for AJAX utilities. Utilities filled gaps in early JavaScript; modern ES6+ provides native alternatives (Array.map, Object.assign). jQuery utilities remain useful for consistency and cross-browser support in legacy code.
72. What is $.each() and how does it differ from .each()?
$.each() is a utility function iterating over arrays and objects: $.each(array, function(index, value){}), working on plain JavaScript data. .each() is a jQuery object method iterating over matched elements: $('div').each(function(index, element){}). $.each() is general-purpose; .each() specifically for jQuery collections. Inside .each(), 'this' refers to current element. Both support returning false to break. $.each() handles objects (iterating properties) and arrays; .each() works on jQuery collections. Modern forEach() often replaces $.each(); .each() remains useful for jQuery collections. Use appropriate method based on data type.
73. What is $.extend() and how do you use it?
$.extend() merges objects, copying properties from source objects to target: $.extend(target, source1, source2). First parameter as true enables deep copy: $.extend(true, {}, source) recursively copies nested objects. Without deep flag, performs shallow merge. Commonly used for options/settings: var settings = $.extend({}, defaults, userOptions). Modifies first object unless empty object provided. Later sources override earlier ones. $.extend() was essential before Object.assign() and spread operator. Still useful for deep merging (Object.assign is shallow). Understanding shallow vs deep copy prevents unintended mutations.
74. How do you traverse DOM in jQuery?
jQuery provides traversal methods: .find() searches descendants, .children() gets direct children, .parent() gets immediate parent, .parents() gets all ancestors, .closest() finds nearest ancestor matching selector. .siblings() gets sibling elements, .next()/.prev() get adjacent siblings. .filter() reduces matched set, .not() excludes elements, .eq() selects by index. Use .first()/.last() for first/last elements. .has() filters by descendants. Traversal is chainable: $('div').find('.inner').parent(). Understanding traversal is crucial for navigating DOM efficiently. Modern querySelector can often replace complex traversals.
75. What is the difference between .prop() and .attr()?
.prop() accesses JavaScript properties (element.checked, element.disabled), reflecting current state. .attr() accesses HTML attributes (what's in markup), reflecting initial state. For boolean attributes (checked, disabled, selected), use .prop(). For data-* attributes or custom attributes, use .attr(). Example: checkbox checked property changes with clicks (.prop()), but checked attribute remains unchanged (.attr()). .prop() is for runtime state, .attr() for markup. jQuery 1.6+ distinguished these; earlier versions conflated them. Understanding the difference prevents bugs with form elements and boolean attributes.
76. What are jQuery plugins and how do you create one?
jQuery plugins extend jQuery functionality, created by adding methods to $.fn (jQuery.prototype): $.fn.myPlugin = function(options){}. Follow patterns: support chaining (return this), handle options with $.extend(), work with collections using .each(). Namespace plugins to avoid conflicts. Example: $.fn.highlight = function(color){return this.css('background', color);}. Use closure for private functions. Plugins made jQuery extensible; thousands exist (validation, carousels, etc.). Modern development prefers web components or framework components, but jQuery plugins pioneered component reuse. Creating plugins teaches prototypal extension and API design patterns.
77. What is jQuery.noConflict()?
jQuery.noConflict() releases jQuery's control of the $ variable, allowing other libraries using $ to coexist. Returns jQuery object for alternative naming: var jq = jQuery.noConflict(). After calling, use jQuery or your alias instead of $. Useful when multiple libraries (Prototype, MooTools) used $. Pass true to release both $ and jQuery: var jq = jQuery.noConflict(true). Wrap code in IIFE with $ parameter: (function($){/*code*/})(jQuery) to keep $ locally. NoConflict was essential for library interoperability. Modern module systems reduce conflicts, but understanding noConflict helps maintain legacy code.
78. How do you detect if an element exists in jQuery?
Check .length property: if($('#element').length){}. jQuery selectors always return objects (never null), so check length to see if elements matched. Use .length > 0 or just .length (truthy). Alternative: if($('#element').length !== 0){}. Don't use if($('#element')) as it's always truthy. Check existence before operations to avoid errors. Modern vanilla JS uses if(document.querySelector('#element')){}. Understanding that jQuery always returns objects prevents conditional logic errors. The .length check is idiomatic jQuery for existence testing.
79. What is the difference between $(this) and this in jQuery?
Inside jQuery event handlers or .each(), 'this' refers to the raw DOM element (native JavaScript object). $(this) wraps it in jQuery object, enabling jQuery methods. Use 'this' for native properties (this.id, this.value) which is faster. Use $(this) for jQuery methods: $(this).hide(), $(this).addClass(). Example: this.style.color vs $(this).css('color'). $(this) has overhead of creating jQuery object. Best practice: use 'this' when possible for performance, $(this) when needing jQuery functionality. Understanding the distinction improves performance and prevents errors from calling jQuery methods on raw DOM.
80. How do you get and set data attributes in jQuery?
Use .data() to get/set data attributes: .data('key') gets, .data('key', value) sets. jQuery converts data-key-name to keyName (camelCase). .data() stores data in internal cache, not always updating HTML attribute. Use .attr('data-key') for direct attribute access. .data() performs type conversion (strings to numbers/booleans). .removeData() removes cached data. Data attributes useful for storing element metadata. HTML5 formalized data-* attributes. Modern dataset API provides native alternative: element.dataset.key. .data() was revolutionary for associating data with elements cleanly.

πŸ“ jQuery Forms & Validation

81. How do you work with forms in jQuery?
jQuery provides form-specific methods: .val() gets/sets input values, .serialize() converts form to query string, .serializeArray() creates array of objects. Use :input, :text, :checkbox, :selected selectors for form elements. .submit() triggers or handles form submission. Prevent default submission: $('form').on('submit', function(e){e.preventDefault();}). Access form data with .val() or iterate inputs with .each(). jQuery simplifies form handling that was tedious in vanilla JS. Modern FormData API provides native serialization. Understanding jQuery form methods essential for legacy code and AJAX form submissions.
82. What is .serialize() and .serializeArray()?
.serialize() converts form inputs to URL-encoded query string: 'name=John&age=30', ready for GET requests or AJAX data. .serializeArray() creates array of objects: [{name: 'name', value: 'John'}], useful for manipulation before submission. Both include only successful controls (not disabled, must have name). .serialize() is simpler for direct submission; .serializeArray() for processing/validating before sending. Neither includes file inputs or buttons. Useful for AJAX form submissions without page refresh. Modern FormData() provides similar functionality with additional features. Understanding serialization methods streamlines form handling in jQuery applications.
83. How do you validate forms with jQuery?
Manual validation: check .val() for empty, use regex for patterns, validate on submit or blur events. jQuery Validation plugin provides comprehensive solution: rules (required, email, minLength), custom messages, inline error display, and customization. Example: $('form').validate({rules: {email: {required: true, email: true}}}). Combine with HTML5 validation attributes. Show errors with .addClass('error'), remove with .removeClass(). Disable submit until valid. Modern HTML5 validation and frameworks provide built-in validation, but jQuery validation remains powerful for complex scenarios and legacy applications.
84. What are jQuery form selectors?
jQuery provides form-specific pseudo-selectors: :input (all form elements), :text, :password, :radio, :checkbox, :submit, :image, :reset, :button, :file for input types. :enabled/:disabled for state, :checked for checkboxes/radios, :selected for option elements. Example: $(':checkbox:checked') gets checked checkboxes. These selectors simplified form element targeting. Modern querySelectorAll supports most via [type="checkbox"] but lacks some jQuery pseudo-selectors. :checked remains useful. Understanding form selectors essential for dynamic form manipulation. Combine with .filter() or .not() for complex selections.
85. How do you handle checkboxes and radio buttons in jQuery?
Use .prop('checked') to get/set checked state: $('input').prop('checked', true). Use :checked selector: $('input:checked') gets checked elements. Listen for change event: $('input').on('change', function(){}). For radio groups, get selected: $('input[name="group"]:checked').val(). Checkboxes can be checked individually; radios auto-uncheck others in same name group. Use .is(':checked') to test state. .val() on checkboxes returns value attribute, not checked state. Understanding property vs attribute crucial here. Modern approaches use form data or state management, but jQuery patterns remain relevant.

πŸš€ jQuery Performance & Best Practices

86. What are jQuery performance best practices?
Cache selectors: var $div = $('div') instead of repeatedly calling $('div'). Use ID selectors (fastest) when possible. Chain methods to reduce selections. Use event delegation for dynamic elements. Minimize DOM manipulation; batch changes or use document fragments. Avoid unnecessary animations. Use .find() on cached parents instead of complex selectors. Detach elements during heavy manipulation with .detach(). Load jQuery from CDN for caching. Use specific selectors; avoid universal selector. Modern development often avoids jQuery for performance, but understanding these practices improves any DOM manipulation code.
87. Why should you cache jQuery selectors?