1. How can you create a function in Javascript?
They are created using the keyword function. They have parameters that we set within parentheses, and a body, which contains the expression to be executed.
A function may look like the following:
const power = function(base, exponent) {
let result = 1;
for (let count = 0; count < exponent; count++) {
result *= base;
}
return result;
};
In the parentheses following function, we set the parameters. Parameters may be empty, or have one or several values. When calling the function, should we use too many parameters, like below:
function square(x) { return x * x; }
console.log(square(4, true, "hedgehog"));
// → 16
The program will ignore the extra parameters. Should we use too few, the program will assign undefined to the forgotten parameters. This can be bad, because we can create mistakes without the system telling us about it, but could also prove useful such as below:
function minus(a, b) {
if (b === undefined) return -a;
else return a - b;
}
console.log(minus(10));
// → -10
console.log(minus(10, 5));
// → 5
We can assign default values to parameters in order to circumvent those situations, or simply if needed, by writing an equal sign after the parameter. For example:
function power(base, exponent = 2) {
let result = 1;
for (let count = 0; count < exponent; count++) {
result *= base;
}
return result;
Here the default value for exponent is 2.
Therefore:
console.log(power(4));
// → 16
In braces, we have the body of the function, containing the statement to be executed when the function is called. The return statement determines the value to be returned by the function. The code will be read and when it hits the return statement, jumps out of the function to give back the result. Failure to define a return statement will give undefined.
In the first function above, the binding, const was declared. Doing so submits the function to the normal control flow of the program, i.e. top to bottom and left to right:
console.log("The future says:", future());
const future = function () {
return "You'll never have flying cars";
}
We get an error because we are trying to use a function called future, that we define after calling it with console.log. There is another way to define functions, that doesn’t submit it to the control flow:
console.log("The future says:", future());
function future() {
return "You'll never have flying cars";
}
simply using the keyword function, and then naming it will allow you to create a function and use it anywhere in the code.
A third and final way to declare functions is using the “implies” sign:
const power = (base, exponent) => {
let result = 1;
for (let count = 0; count < exponent; count++) {
result *= base;
}
return result;
};
The differences compared to the function declaration are minor.
- What is the difference between var and let in regards to scope?
The scope of a binding is the part of the program in which is the binding is visible. Global bindings are defined outside the scope of any function and can be called at any point in the program. When defined inside a function though, those bindings are called local and can only be used within that function. The bindings are therefore created again every time the function is called. This provides a quarantine and ensure that each function can operate separately. As a result, it is possible to read the function and understand it without knowing the global program.
Var is the historical way to create a binding and is visible throughout the program. It used to be that only bindings within a function were local. Const and let were introduced to enable local bindings only visible in the block they are in, i.e. only inside the curly brackets. Here is an example of the side effects:
let x = 10;
if (true) {
let y = 20;
var z = 30;
console.log(x + y + z);
console.log(y);
//Syntax error
console.log(x+z);
//40
Here, X is out of the block, therefore when called outside of it, even when using let, a result back is given. Y is in the block, and let is used to bind it, so when called, no result is given. Z is in the block, but var is used to bind it. So when called it works perfectly.
When using different bindings with the same name, should a function be called, it will use its inner binding, not the “global” one:
const halve = function(n) {
return n / 2;
};
let n = 10;
console.log(halve(100));
// → 50
console.log(n);
// → 10
When nesting functions, the inner function may see the outer bindings as well as its own, but the outter function cannot:
const hummus = function(factor) {
const ingredient = function(amount, unit, name) {
let ingredientAmount = amount * factor;
if (ingredientAmount > 1) {
unit += "s";
}
console.log(`${ingredientAmount} ${unit} ${name}`);
};
ingredient(1, "can", "chickpeas");
ingredient(0.25, "cup", "tahini");
ingredient(0.25, "cup", "lemon juice");
ingredient(1, "clove", "garlic");
ingredient(2, "tablespoon", "olive oil");
ingredient(0.5, "teaspoon", "cumin");
};
Here the function ingredient can see the bindings of function hummus, but hummus cannot see the bindings of ingredient. Therefore the visibility is “upward”, I can see what is up there, not “downward”, those that are up cannot see what is down there. This approach to binding is called lexical scoping.
- What is a pure function?
A pure function is a value producing function, therefore has no side effects, and that does not rely on side effects from other lines of code. It does not read global bindings and will always return the same results when input with the same arguments and does not do anything else. They are easier to test than non pure functions. They need not be an obsession though, as side effects might be useful to optimize execution time.