It’s always pass by value, but for objects the value of the variable is a reference. Because of this, when you pass an object and change its members, those changes persist outside of the function. This makes it look like pass by reference. But if you actually change the value of the object variable you will see that the change does not persist, proving it’s really pass by value.
The this
keyword refers to different things in different context and that is the may reason it can be troublesome. This is a short summary of what this
can mean in different contexts. The easiest rule of thumb - always prefer arrow functions as there behavior is the most ‘normal’.
null
, undefined
, or undeclared
?undeclared
when it does not use the var keyword. It gets created on the global object (that is, the window), thus it operates in a different space as the declared variables. Note: This will not work in strict mode plus you really should not use global variables.undefined
when it hasn’t been defined yet. If you call a variable or function without having actually created it yet the parser will give you an not defined error.null
is a variable that is defined to have a null value.Or in short:
undeclared
variables don’t even existundefined
variables exist, but don’t have anything assigned to themnull
variables exist and have null assigned to them===
and !==
operator?This is strict equality. For strict equality the objects being compared must have the same type and:
NaN
is not equal to anything, including NaN. Positive and negative zeros are equal to one another.Object
.Null
and Undefined
types are ==
(but not ===
). [I.e. (Null == Undefined
) is true
but (Null === Undefined
) is false
]In ES5 creating true private method in javascript is very memory inefficient because a new copy of the method would be created for each instance. This will change with ES9 as there is a Stage 3 proposal for private methods:
typeof bar === "object"
to - determine if bar is an object? How can this pitfall be avoided?Null
and Array
is also considered objects! In order to avoid this behavior check explicitly for these cases.
Anonymous function are just functions declarations without a name. Every time you write the function keyword, anywhere in your code, giving it a name right after is actually optional. Omitting the name makes the function, well, anonymous.
It is a term used in dynamic languages that do not have strong typing. The idea is that you don’t need a type in order to invoke an existing method on an object - if a method is defined on it, you can invoke it. The name comes from the phrase “If it looks like a duck and quacks like a duck, it’s a duck”.
Functions in JavaScript are first-class objects. You can pass them into other functions as arguments just like any other object and these parameter functions are called higher order functions.
Currying is when you break down a function that takes multiple arguments into a series of functions that take part of the arguments.
function add (a, b) {
return a + b;
}
add(3, 4); // returns 7
// Same function using curring.
function add (a) {
return function (b) {
return a + b;
}
}
They are mostly similar except:
There are two major differences:
this
and arguments
- Arrow functions don’t have their own this or arguments binding. Instead, those identifiers are resolved in the lexical scope like any other variable. That means that inside an arrow function, this and arguments refer to the values of this and arguments in the environment the arrow function is defined in (i.e. “outside” the arrow function).new
A promise is an object that may produce a single value some time in the future: either a resolved value, or a reason that it’s not resolved (e.g., a network error occurred). A promise may be in one of 3 possible states: fulfilled, rejected, or pending. Promise users can attach callbacks to handle the fulfilled value or the reason for rejection.
Array.isArray()
The difference is that apply lets you invoke the function with arguments as an array; call requires the parameters be listed explicitly. A useful mnemonic is “A for array and C for comma.”
In short function hoisting means that functions are moved to the top of their scope. NEVER depend on hoisting as it can produce unexpected behavior.
A very complex question but in short:
You should always prefer let
over var
.
let
has block scoping and var
is function scoped - this may lead to strange behavior as variable declared in a block scope can be accessed ousted of it.let
can be update but not redeclared.var
, let
declarations are hoisted to the top. Unlike var
which is initialized as undefined, the let
keyword is not initialized. So if you try to use a let variable before declaration, you’ll get a Reference Error
.const
cannot be updated or re-declared BUT there is some specific behavior:
const
Array.Destructuring assignment is a special syntax that allows us to “unpack” arrays or objects into a bunch of variables, as sometimes they are more convenient. Destructuring also works great with complex functions that have a lot of parameters, default values, and soon we’ll see how these are handled too.
A generator is a function that can stop midway and then continue from where it stopped. In short, a generator appears to be a function but it behaves like an iterator.
Lazy Evaluation is an evaluation model which delays the evaluation of an expression until its value is needed. That is, if we don’t need the value, it won’t exist. It is calculated as we demand it. Generators are lazy evaluated.
Asynchronous: Go away and do this task, when you’re finished come back and tell me and bring the results. I’ll be getting on with other things in the mean time.
In JavaScript we can use callbacks, Promises and async/await to do async programing and WebWorkers to do parallel programming.
The main reason is the shared state problem:
The problem with global variables is that since every function has access to these, it becomes increasingly hard to figure out which functions actually read and write these variables.
To understand how the application works, you pretty much have to take into account every function which modifies the global state. That can be done, but as the application grows it will get harder to the point of being virtually impossible (or at least a complete waste of time).
If you don’t rely on global variables, you can pass state around between different functions as needed. That way you stand a much better chance of understanding what each function does, as you don’t need to take the global state into account.
When an event is triggered on an element, for example a mouse click on a button, the same event is also triggered on all of that element’s ancestors. This process is known as event bubbling;
If you have a function that gets called a lot - for example when a resize or mouse move event occurs, it can be called a lot of times. If you don’t want this behaviour, you can Throttle it so that the function is called at regular intervals. Debouncing will mean it is called at the end (or start) of a bunch of events.
The event loop is a fundamental aspect of Node.js that enables its non-blocking, asynchronous behavior. It is the core mechanism that allows Node.js to handle multiple operations simultaneously without the need for multiple threads.
setTimeout()
and setInterval()
.setImmediate()
.setImmediate()
callbacks are invoked here.socket.on('close', ...)
.In a Node.js application, when an asynchronous function is called, it is processed outside the main thread. The event loop continuously checks the callback queue for any callbacks that need to be executed. If it finds one, it removes it from the queue and executes it.
This mechanism allows Node.js to perform heavy I/O operations without blocking the single thread, making it highly scalable for I/O-bound tasks.
In summary, the event loop is a core concept in Node.js that enables asynchronous programming by allowing long-running operations to be processed without blocking the main thread.
Six data types that are primitives:
and Object
module.export
syntaximport/export
syntaxeval
bad?The scope chain is a fundamental concept in many programming languages, including JavaScript, that defines how variable names are resolved in nested scopes.
For example:
let globalVar = "global";
function outerFunction() {
let outerVar = "outer";
function innerFunction() {
let innerVar = "inner";
// Here, innerFunction's scope chain is [innerFunction's scope, outerFunction's scope, global scope]
console.log(innerVar); // Resolves to "inner"
console.log(outerVar); // Resolves to "outer" via scope chain
console.log(globalVar); // Resolves to "global" via scope chain
}
innerFunction();
}
outerFunction();