This article lists the almost aspect of JavaScript Array. The content is mainly from [MDN]((https://developer.mozilla.org), but shorter and convenient for it is in one article.
Define a function
Function definition/declaration
A function definition consist:
function
keyword.- A parameter list enclosed in
()
. - JavaScript statements enclosed in
{}
.
Example:
function square(number) {
return number * number;
}
Parameters are passed by value or by reference
Primitive parameters are passed by value which means changes to parameters inside the function are not reflected outside the function.
For non-primitive parameters like objects, the changes to the parameters inside the function are visible outside it.
Function expression
A function in JavaScript can also be a form of a a function expression.
It can be anonymous or has a name.
Examples:
// Anonymous function expression
const square = function(number) { return number * number };
var x = square(4); // x gets the value 16
const factorial = function fac(n) { return n < 2 ? 1 : n * fac(n - 1) };
console.log(factorial(3));
They are convenient when being as an argument passed to another function:
// map(f, a) is a function that accepts a function as the first parameter.
function map(f, a) {
let result = [];
let i;
for (i = 0; i != a.length; i++)
result[i] = f(a[i]);
return result;
}
// Call map(f, a) to pass it a function the first parameter.
const f = function(x) {
return x * x * x;
}
let numbers = [0, 1, 2, 5, 10];
let cube = map(f,numbers);
console.log(cube); // [0, 1, 8, 125, 1000]
Define a function based on a condition
In JavaScript, a function can be defined based on a condition:
let myFunc;
if (num === 0) {
myFunc = function(theObject) {
theObject.make = 'Toyota';
}
}
Function constructor
Every JavaScript function is actually a Function
object. The Function constructor Function()
creates a new Function
object dynamically.
let helloFunc = new Function('console.log("Hello")');
Note
Calling the constructor directly can create functions dynamically but suffers from security and similar (but far less significant) performance issues to
Global_Objects/eval
. However, unlike eval, theFunction
constructor creates functions that execute in the global scope only.
Difference between Function constructor and function declaration
Functions created with the Function
constructor do not create closures to their creation contexts; they always are created in the global scope. When running them, they will only be able to access their own local variables and global ones, not the ones from the scope in which the Function
constructor was created. This is different from using Global_Objects/eval
with code for a function expression.
var x = 10;
function createFunction1() {
var x = 20;
return new Function('return x;'); // this |x| refers global |x|
}
function createFunction2() {
var x = 20;
function f() {
return x; // this |x| refers local |x| above
}
return f;
}
var f1 = createFunction1();
console.log(f1()); // 10
var f2 = createFunction2();
console.log(f2()); // 20
While this code works in web browsers, f1()
will produce a ReferenceError
in Node.js, as x
will not be found. This is because the top-level scope in Node is not the global scope, and x
will be local to the module.
Function scope
A function can access all variables and functions defined inside the scope in which it is defined.
Nested functions
Functions can be nested. The nested (inner) function is private to its containing (outer) function.
Example1
function addSquares(a, b) {
function square(x) {
return x * x;
}
return square(a) + square(b);
}
a = addSquares(2, 3); // returns 13
b = addSquares(3, 4); // returns 25
c = addSquares(4, 5); // returns 41
Example2
function A(x) {
function B(y) {
function C(z) {
console.log(x + y + z);
}
C(3);
}
B(2);
}
A(1); // logs 6 (1 + 2 + 3)
Closure
Since the inner function has access to the scope of the outer function, the variables and functions defined in the outer function will live longer than the duration of the outer function execution, if the inner function manages to survive beyond the life of the outer function. A closure is created when the inner function is somehow made available to any scope outside the outer function.
A complex example
var createPet = function (name) {
var sex;
return {
setName: function (newName) {
name = newName;
},
getName: function () {
return name;
},
getSex: function () {
return sex;
},
setSex: function (newSex) {
if (typeof newSex === 'string' && (newSex.toLowerCase() === 'male' ||
newSex.toLowerCase() === 'female')) {
sex = newSex;
}
}
}
}
var pet = createPet('Vivie');
pet.getName(); // Vivie
pet.setName('Oliver');
pet.setSex('male');
pet.getSex(); // male
pet.getName(); // Oliver
An object (Here it is the object returned by createPet()
) containing methods for manipulating the inner variables of the outer function can be returned.
Another example: The outside function does not even have to be assigned to a variable, or have a name. It is called when defined and the returned inner function is assigned to getCode
. getCode()
means calling the inner function which returns apiCode
.
var getCode = (function() {
var apiCode = '0]Eal(eh&2';// A code we do not want outsiders to be able to modify...
return function() {
return apiCode;
};
})();
getCode(); // Returns the apiCode
Function parameters
Default parameters
// Default parameters
function multiply(a, b = 1) {
return a * b;
}
multiply(5); // 5
Indefinite number of arguments
// Indefinite number of arguments
function multiply(multiplier, ...theArgs) {
return theArgs.map(x => multiplier * x);
}
var arr = multiply(2, 1, 2, 3);
console.log(arr); // [2, 4, 6]
The arguments object
The arguments of a function are maintained in an array-like object. Within a function, you can address the arguments passed to it as follows:
function myConcat(separator) {
let result = ''; // initialize list
// Iterate through arguments
for (let s of arguments) {
result += s + separator;
}
return result;
}
myConcat(', ', 'red', 'orange', 'blue'); // ", , red, orange, blue, "
Arrow function
An arrow function expression (previously, and now incorrectly known as fat arrow function) has a shorter syntax compared to function expressions and does not have its own this
, arguments, super, or new.target. Arrow functions are always anonymous.
Let’s see an example difference using a function and using an arrow function as a parameter (callback).
Use a function:
Until arrow functions, every new function defined its own
this
value (a new object in the case of a constructor, undefined in strict mode function calls, the base object if the function is called as an “object method”, etc.). This proved to be less than ideal with an object-oriented style of programming.
function Person() {
this.age = 0;
var self = this; // Some choose `that` instead of `self`.
// Choose one and be consistent.
setInterval(function growUp() {
// The callback refers to the `self` variable of which
// the value is the expected object.
self.age++;
}, 1000);
}
Inside growUp()
, it can not refer to this
(the Person
Function object) directly for it has its own this
.
Tips
Alternatively, a bound function (Use
bind()
to create a new function that, when called, has itsthis
keyword set to the provided value) could be created so that the properthis
value would be passed to thegrowUp()
function.function Person() { this.age = 0; let growUp = function () { this.age++; }; let boundedGrowup = growUp.bind(this); setInterval(boundedGrowup, 1000); }
Use an arrow function:
function Person() {
this.age = 0;
setInterval(() => {
this.age++; // |this| properly refers to the person object
}, 1000);
}
var p = new Person();
An arrow function does not have its own this
, the this
value of the enclosing execution context is used.
Pass extra parameter to a callback
onload
accepts no parameters, to pass extra parameters to it:
avatar.onload = (function (context, avatar) {
return function () {
context.drawImage(avatar, 20, 100, 64, 64);
}
})(context, avatar);