1. Variable Declaration
2. Variable Assignment
var name;
var age;
var favoriteColor;
name = "Elie";
age = 74;
favoriteColor = "purple";
var name = "Whiskey";
var age = 4;
var favoriteColor = null;
Using a keyword (e.g. "var") to set aside space for some data.
Using an assignment operator (e.g. "=") to set a value
Variable declaration with assignment
Just remember that declaration always happens first!
3. Function Declaration
4. Function Expression
function addTwo(x, y) {
return x + y;
}
var addTwoFunc = function addTwo(x, y) {
return x + y;
}
var subtractTwo = function(x, y) {
return x - y;
}
Using the function keyword lets you declare a function.
Assign a function to a variable in-line
5. Anonymous Function
Outside of a function declaration, functions do not need names
6. Function Call / Invocation
function addTwo(x, y) {
return x + y;
}
addTwo(99, 1); // 100
Run the code in the function body with its name followed by parentheses ()
7. Parameters
variables declared when defining a function
8. Arguments
Values you assign ("pass") to parameters.
Every function has a built-in arguments array of values.
9. Return Value
The value resolved by the return statement inside the function. The default is undefined.
10. Methods
In JavaScript, we call generally call functions "methods" when they live on data types.
var myArr = [];
myArr.push(5); // push is a method
function printList(arr) {
for (let i of arr) {
console.log(arr);
}
}
printList(myArr); // printList is a regular old function
If you called anything.something(), then .something() would be referred to as a method.
Like most programming languages, JavaScript uses lexical scoping, which means variables are by default attached to the scope where they are originally declared in the code.
Note: JavaScript also utilizes dynamic scope using the "this" keyword, but that is an advanced topic for another time.
var name = 'Michael'; // global scope by default
// ... 10 thousand lines later ...
console.log(name); // Michael (assuming it hasn't been reassigned)
In JavaScript, most often we will use functions to create new layers of scope.
var scopey = 'I was declared in the global scope.';
function newScope() {
var scopey = 'I was declared in the inner scope';
console.log(scopey);
}
console.log(scopey);
// I was declared on the global scope
newScope();
// I was declared in the inner scope
Shadowing
var rithm = 'rithm'; // global scope
parentFunction(myArg) {
console.log(rithm);
}
childFunction(){ console.log(myArg, rithm);
}
Scopes can be nested within each other predictably:
parentFunction('Algo'); // Algorithm
childFunction();
var globalScope = 'I am in the global scope.';
function outer() {
console.log(globalScope);
var outerScope = "I am in the outer function's scope";
inner(); // note this function is "hoisted"
function inner() {
console.log(outerScope);
console.log("I am in the inner function's scope");
}
}
console.log(globalScope);
// I am in the global scope.
console.log(outerScope);
// undefined
outer();
// I am in the global scope.
// I am in the outer function's scope.
// I am in the inner function's scope.
inner(); // ReferenceError: inner is not defined
1. In JavaScript, the default scope is lexical, meaning variables live in the scope where they were physically declared in the code
2. Use functions to create different scopes. Function parameters are scoped inside the function the same as if they said "var x" at the top of the function body.
3. Scopes can be nested. A child scope can access variables in parent scopes. A parent scope cannot access variables in its children's scopes.
JavaScript has first class functions, meaning that functions can be treated just like other data types
We've seen this before with function expressions:
var favorite = function(thing, value) {
return `My favorite ${thing} is ${value}.`;
}
console.log(favorite('food', 'pizza'));
// My favorite food is pizza.
In the above example, when the variable favorite gets assigned to a function, we can invoke it like one!
function first(anotherFunc) {
// SPOILER ALERT! I AM A HOF!
return anotherFunc();
}
function second() {
console.log('hello Whiskey');
}
first(second); // hello Whiskey
Function parameters can be designed to expect functions as arguments.
Here is a function that receives a function as an argument and then invokes its argument in its function body:
Math Nerd Alert!
Higher Order Functions are more of a mathematical concept rather than a feature specific to programming languages.
A Higher Order Function (often abbreviated HOF) is a function that does at least one of the following (or both):
function myHOF(myFunc, myArg) {
return myFunc(myArg);
}
myHOF(console.log, 'hello from the HOF');
// hello from the HOF
Here's a HOF that takes a function with an argument, and calls it.
Lots of built-in functions in JavaScript are Higher Order Functions (HOFs) that are designed to accept callbacks.
The callback pattern usually looks like this:
function greeting(name) {
alert('Hello ' + name);
}
function processUserInput(callback) {
var name = prompt('Please enter your name.');
callback(name);
}
processUserInput(greeting);
Usually callbacks are defined in-line with anonymous functions.
function eachItem(obj, cb) {
for (let key in obj) {
cb(key, obj[key]);
}
}
let obj = { name: 'Whiskey', otherName: 'Hazel' };
eachItem(obj, function(key, val) {
console.log('The key is ' + key + '. the value is ' + val + '.');
});
// The key is name. The value is Whiskey.
// The key is otherName. The value is Hazel.
We'll discuss the following functions that all take callbacks:
1. setTimeOut
2. Array forEach
3. Array map
4. Array filter
5. Array reduce
6. Array sort
setTimeout(function() {
alert('yoooo');
}, 1000);
[1,2,3].forEach(function(element, index) {
console.log(element, index);
});
/*
1 0
2 1
3 2
*/
var oldArr = [1,2,3];
var newArr = oldArr.map(function(element, index) {
return element * index;
});
console.log(newArr);
/*
[0, 2, 6]
*/
var oldArr = [1,2,3,4,5,6,7,8,9,10]
var newArr = oldArr.filter(function(element, index) {
return element % 2 === 0;
});
console.log(newArr);
/*
[2, 4, 6, 8, 10]
*/
var oldArr = [3, 2, 1]
var countDown = oldArr.reduce(function(previous, current, index) {
return previous + ' ' + current;
}, "ready");
console.log(countDown);
/*
ready 3 2 1;
*/
var myArr = [10, 3, 2, 7, 9, 11, 1];
myArr.sort(function(a, b) {
return a - b;
})
console.log(myArr);
/*
1, 2, 3, 7, 9, 10, 11
*/