My Docs
Search…
Understanding By Example

Functions:

1
# Function Context Cheatsheet
2
​
3
## Types of Invocation
4
- Applies to only **named** and **unnamed** functions
5
- **Doesn't matter** for fat arrow functions
6
​
7
### Function-style invocation
8
- Context of the function will be global context **UNLESS** binded
9
​
10
### Method-style invocation
11
- Context of the function will be the object which the function is called on **UNLESS** binded
12
​
13
```javascript
14
const obj = {
15
name: 'Example Object',
16
unnamedFunc: function() {
17
console.log(this.name);
18
}
19
};
20
​
21
// Method-style invocation
22
obj.unnamedFunc(); // 'Example Object'
23
​
24
// Function-style invocation
25
const unnamedFunc = obj.unnamedFunc;
26
unnamedFunc(); // Global context
Copied!

Types of Functions

Named Function

  • explicit return keyword required
  • curly braces {} around function body
  • NOT saved to a variable
  • parameters must be surrounded by parentheses ()
  • context is defined by how it's invoked or called
    • function-style: global context
    • method-style: context is object that function is being called on
  • calling bind on the function will return a function binded to the context of the bind argument
1
function namedFunc(params) {
2
return 'named function'
3
}
Copied!
1
// bindedNamedFunc will have the context of obj
2
const bindedNamedFunc = namedFunc.bind(obj);
Copied!

Unnamed Function

  • explicit return keyword required
  • curly braces {} around function body
  • MUST be saved to a variable
  • parameters must be surrounded by parentheses ()
  • context is defined by how it's invoked or called
    • function-style: global context
    • method-style: context is object that function is being called on
  • calling bind on the function will return a function binded to the context of the bind argument
1
const unnamedFunc = function(params) {
2
return 'unnamed function'
3
}
Copied!
1
// bindedUnnamedFunc will have the context of obj
2
const bindedUnnamedFunc = unnamedFunc.bind(obj);
Copied!

Explicit Fat Arrow Function

  • explicit return keyword required
  • curly braces {} around function body
  • MUST be saved to a variable
  • parameters must be surrounded by parentheses () IF more than one parameter
  • takes the context of where it's defined
  • CANNOT be binded using bind
1
const explicitFatArrow = params => {
2
return 'explicit fat arrow function'
3
};
Copied!

Implicit Fat Arrow Function

  • NO return keyword
  • function body can only consist of what is being returned
  • Optional parentheses () around function body
    NOTE: Parentheses needs to be used if returning an object ex: ({ key: value })
  • MUST be saved to a variable
  • parameters must be surrounded by parentheses () IF more than one parameter
  • takes the context of where it's defined
  • CANNOT be binded using bind
1
const implicitFatArrow = (params) => 'implicit fat arrow function';
Copied!
1
const implicitFatArrow = (params) => ('implicit fat arrow function');
Copied!
1
const implicitFatArrow = (params) => ({
2
function: 'implicit fat arrow'
3
});
Copied!

Bind

  • bind accepts multiple arguments
  • first argument is the context that you want to bind the function to
  • any arguments that come afterwards will be passed in when the bound function is called BEFORE the call time arguments
    ```
1
// Arrow Functions
2
// 1. Syntax
3
// 2. Scoping with Arrow Functions
4
​
5
function logger(title, body) {
6
console.log("\x1b[31m%s\x1b[0m", title);
7
console.log(' ', body);
8
}
9
​
10
// Named Function
11
function sayHelloNamed(name) {
12
return 'hello ' + name;
13
}
14
​
15
logger('Named Function', sayHelloNamed('Justin'));
16
​
17
// Unnamed Function
18
const sayHelloUnnamed = function(name) {
19
return 'hello ' + name;
20
};
21
​
22
logger('Unnamed Function', sayHelloUnnamed('Soon-Mi'));
23
​
24
​
25
​
26
​
27
​
28
​
29
​
30
// Fat Arrow Function with EXPLICIT return
31
// curly braces around body of fat arrow functions need explicit return keyword
32
// const sayHelloExplicit = (name) => {
33
// return 'hello ' + name;
34
// };
35
​
36
// No parentheses surrounding parameter needed if ONLY one parameter
37
const sayHelloExplicit = name => {
38
return 'hello ' + name;
39
};
40
​
41
logger('Fat Arrow Function with Explicit Return', sayHelloExplicit('Gordon'));
42
​
43
​
44
​
45
​
46
​
47
​
48
​
49
​
50
​
51
​
52
​
53
​
54
// Fat Arrow Function with IMPLICIT return
55
// Also called a One-Liner Fat Arrow function
56
// should only use this when the function's body is NOT multi-line
57
const sayHelloImplicit = (name) => 'hello' + name;
58
​
59
// can use parentheses around function body as well
60
// const sayHelloImplicit = (name) => ({
61
// hello: 'Angela'
62
// });
63
​
64
// notice the semicolon ; at the end
65
​
66
logger('Fat Arrow Function with Implicit Return', sayHelloImplicit('Angela'));
67
​
68
​
69
​
70
​
71
​
72
​
73
console.log('\n--------------\n');
74
​
75
​
76
​
77
​
78
// Example using fat arrow functions
79
const arr = [1, 2, 3];
80
​
81
const newArr = arr.map(el => {
82
return el + 2;
83
});
84
// const newArr = arr.map(function(el) {
85
// return el + 2;
86
// });
87
​
88
logger('Original Array, `arr`', arr);
89
logger('New Mapped Array, `newArr`', newArr);
90
​
91
​
92
​
93
​
94
console.log('\n--------------\n');
95
​
96
​
97
​
98
​
99
​
100
​
101
// Context using Fat Arrow functions
102
const pony = {
103
name: 'Lucy',
104
wrappedSayName: function() {
105
console.log(this.name);
106
return function() {
107
console.log(this.name);
108
console.log('Hello my name is ' + this.name);
109
}
110
},
111
wrappedArrowSayName: function() {
112
console.log(this.name);
113
return () => {
114
console.log('Hello my name is ' + this.name);
115
}
116
}
117
};
118
​
119
pony.wrappedSayName = pony.wrappedSayName.bind(pony);
120
let wrap = pony.wrappedSayName().bind(pony); // method-style invocation
121
wrap(); // function-style invocation
122
​
123
console.log('-----------');
124
​
125
wrap = pony.wrappedArrowSayName(); // method-style invocation
126
wrap();
127
​
128
console.log('-----------');
129
​
130
const arrowSayName = pony.wrappedArrowSayName; // not invoking
131
wrap = arrowSayName(); // function-style invocation
132
wrap();
133
​
134
​
135
​
136
// bound to the context of wherever it's defined
137
​
138
​
139
​
140
​
141
​
142
​
143
console.log('-----------');
144
​
145
const zoomMeeting = {
146
students: ['Christian', 'Ronald','Wren'],
147
listStudent: function(studentName) {
148
console.log(this.students);
149
// console.log(studentName);
150
},
151
listStudents: function() {
152
const listStudent = this.listStudent;
153
listStudent(); // function-style
154
console.log('***');
155
this.students.forEach(listStudent);
156
}
157
};
158
​
159
zoomMeeting.listStudents();
Copied!

Scope:

1
// Global Scope
2
​
3
let cities = ["NYC", "SF"];
4
​
5
//console.log(cities);
6
​
7
​
8
​
9
​
10
// Local / Function Scope
11
​
12
​
13
function sayThings() {
14
// let cities = ['Bogota', 'Madrid'];
15
// console.log(cities);
16
​
17
let word = 'dinosaur';
18
console.log(word);
19
}
20
​
21
// console.log(cities); // prints NYC & SF
22
// console.log(word); // ReferenceError
23
//sayThings();
24
​
25
​
26
​
27
​
28
​
29
​
30
​
31
​
32
​
33
​
34
// Block Scope
35
​
36
if (true) {
37
let cats = ['Roma', 'Luigi'];
38
//console.log(cats); // prints Roma & Luigi
39
}
40
​
41
//console.log(cats) // ReferenceError
42
​
43
// This example was extended to show how scope within nested blocks works
44
// As Justin pointed out, it also leads directly into closures
45
​
46
let carrot = 'snake';
47
​
48
if (true){
49
let carrot = 'doggie!';
50
//console.log(carrot);
51
if (true) {
52
carrot = 'carrot';
53
console.log(carrot); // prints carrot
54
}
55
for(let i = 1; i < 5; i++){
56
console.log(`i is ${i}`);
57
};
58
//console.log(`i is ${i}`); // reference error
59
console.log("line 57:" ,'george' ,carrot);
60
}
61
​
62
console.log(carrot); // prints snake
Copied!

Closure

1
// Closure
2
// When an inner function uses, or changes,
3
// variables defined in an outer scope.
4
// NOT for declaring a variable of the same name in an inner scope.
5
function sayHi() {
6
let name = 'Bryan Guner';
7
​
8
function greeting() {
9
// here greeting function closes over, or captures, the name variable
10
// to read it's value
11
return "Hi there, " + name + "!";
12
}
13
// Here, we return the return value of the greeting function
14
return greeting();
15
}
16
// console.log(sayHi());
17
function nameAndCity() {
18
let person = {
19
name: 'Sergey',
20
city: 'Moscow'
21
};
22
​
23
function changeCity() {
24
// here changeCity function closes over the person variable
25
// and reassigns a value on an existing key
26
person.city = 'Toronto';
27
}
28
changeCity();
29
// the person variable will show the changes from the changeCity function
30
return person;
31
}
32
// console.log(nameAndCity());
33
function smoothieMaker() {
34
let ingredients = [];
35
​
36
function addIngredient( ingredient ) {
37
// Here addIngredient function closes over the ingredients variable
38
// to push new elements into the ingredients variable.
39
// We have created a private state where we cannot access
40
// the ingredients array from the outside and can only access
41
// the variable from the inner function.
42
ingredients.push( ingredient );
43
return ingredients;
44
}
45
// Here the return value for smoothiemaker is the return value
46
// is the function addIngredient, NOT addIngredient's return value
47
return addIngredient;
48
}
49
// Here we initialize we return a new addIngredient function
50
// which has closed over the ingredients array
51
const makeSmoothie = smoothieMaker();
52
console.log( makeSmoothie );
53
console.log( makeSmoothie( 'spinach' ) ); // prints [ spinach ]
54
console.log( makeSmoothie( 'turmeric' ) ); // prints [ spinach, turmeric ]
55
// let mySmoothie = makeSmoothie();
56
// Here we return a new and different addIngredient function
57
// which has closed over a new a different ingredients array
58
const makeSmoothie2 = smoothieMaker();
59
console.log( makeSmoothie2( 'kale' ) ); // prints [ kale ] -- does not include spinach and turmeric
60
function createCounter() {
61
let count = 0;
62
return function () {
63
count++;
64
return count;
65
}
66
}
67
let counter1 = createCounter();
68
let counter2 = createCounter();
69
// console.log(counter1());
70
// console.log(counter1());
71
// console.log(counter1());
72
// console.log(counter1());
73
// What will this print out?
74
// console.log(counter2());
75
// Brief talk of scope and redeclaring a const variable in a loop
76
for ( let i = 0; i < 5; i++ ) {
77
const num = i + 2;
78
}
79
​
80
​
81
// In the following examples we will predict what will
82
// be printed to the terminal
83
​
84
​
85
​
86
​
87
​
88
​
89
// 1
90
​
91
function dinerBreakfast(food) {
92
let order = "I'd like cheesy scrambled eggs and ";
93
​
94
function finishOrder() {
95
return order + food;
96
}
97
​
98
return finishOrder();
99
}
100
​
101
// console.log(dinerBreakfast('green tea'));
102
​
103
​
104
​
105
​
106
​
107
​
108
​
109
​
110
​
111
// 2
112
​
113
function dinerBreakfast2(food) {
114
let order = "I'd like a(n) " + food;
115
​
116
function withEggs() {
117
order = order + ' and cheesy scrambled eggs, please!'
118
};
119
​
120
withEggs();
121
return order;
122
}
123
​
124
// console.log(dinerBreakfast2('avocado toast'));
125
​
126
​
127
​
128
​
129
​
130
​
131
​
132
​
133
​
134
// 3
135
​
136
function dinerBreakfast3() {
137
let order = "I'd like cheesy scrambled eggs";
138
​
139
return function (food) {
140
order = order + " and " + food;
141
return order;
142
}
143
}
144
​
145
let breakfastOrder = dinerBreakfast3();
146
​
147
console.log(breakfastOrder);
148
console.log(breakfastOrder('cappuccino'));
149
console.log(breakfastOrder('pancakes'));
Copied!

Context:

1
// In the following examples we will predict what will
2
// be printed to the terminal
3
​
4
​
5
function whatIsThis() {
6
console.log(this);
7
}
8
​
9
const pony = {
10
name: "Lucy",
11
whatIsThis: function () {
12
console.log(this);
13
},
14
sayName: function () {
15
console.log('Hello my name is ' + this.name);
16
},
17
changeName: function (newName) {
18
this.name = newName;
19
this.sayName();
20
}
21
}
22
​
23
​
24
// 1.
25
// whatIsThis();
26
​
27
​
28
// 2.
29
// pony.whatIsThis();
30
​
31
​
32
// 3.
33
// pony.sayName();
34
​
35
​
36
// 4.
37
// pony.changeName("Layla");
38
​
39
​
40
// 5.
41
// const sayNameFunc = pony.sayName;
42
// sayNameFunc();
43
​
44
​
45
// 6.
46
// const boundSayName = pony.sayName.bind(pony);
47
// boundSayName();
48
​
49
​
50
// 7.
51
const bart = {
52
name: 'Bart'
53
}
54
​
55
const boundToBart = pony.sayName.bind(bart);
56
// boundToBart();
57
​
58
​
59
// 8.
60
const changeBartsName = pony.changeName.bind(bart);
61
changeBartsName('Sergey');
62
​
63
​
64
// Context
65
// What does the keyword 'this' refer to?
66
// The context is determined by HOW a function is invoked
67
​
68
​
69
// Different ways of invoking a function
70
// function style
71
// context is set to the global object
72
// 'this' refers to the global object
73
// method style
74
// context is set to the object on which the method is called
75
// 'this' refers to the object on which the method is called
76
​
77
​
78
// How to ensure bind never change the context of a function
79
// no matter how it is invoked.
80
// .bind()
81
// By adding .bind() to the end of a function we set the context
82
// to equal the argument passed to .bind()
83
// 'this' will refer to the argument passed to .bind()
84
​
85
​
86
// Scope VS Context
87
// VERY DIFFERENT THINGS!!
88
​
89
// Scope:
90
// Availability of variables at a line in your application
91
// Context:
92
// The value of this
93
// Determined by how a function has been invoked or the .bind() method
94
​
95
​
96
​
97
​
98
const cat = {
99
name: 'Luigi',
100
age: 2,
101
whatIsThis: function () {
102
console.log(this);
103
},
104
nameAndAge: function () {
105
console.log(this.name + " is " + this.age + " years old.")
106
}
107
};
108
​
109
// cat.whatIsThis();
110
// cat.nameAndAge();
111
​
112
const nameAndAgeFunc = cat.nameAndAge;
113
nameAndAgeFunc();
114
​
115
const boundNameAndAge = cat.nameAndAge.bind(cat);
116
// boundNameAndAge();
117
​
118
​
119
​
120
​
121
​
122
​
123
​
124
​
125
const cat2 = {
126
name: 'Roma',
127
age: 3
128
}
129
​
130
function nameAndAge() {
131
console.log(this.name + " is " + this.age + " years old.");
132
}
133
​
134
const dog = {
135
name: 'Napo',
136
age: 5
137
}
138
​
139
const catNameAge = nameAndAge.bind(cat2);
140
const dogNameAge = nameAndAge.bind(dog);
141
​
142
catNameAge();
143
dogNameAge();
144
​
145
​
146
​
147
​
148
​
149
const obj = {
150
name: 'Example Object',
151
unnamedFunc: function() {
152
console.log(this.name);
153
}
154
};
155
​
156
// Method-style invocation
157
obj.unnamedFunc(); // 'Example Object'
158
​
159
// Function-style invocation
160
const unnamedFunc = obj.unnamedFunc;
161
unnamedFunc(); // `undefined` because Global context
162
​
163
​
164
​
165
​
166
​
167
console.log('-------------------');
168
​
169
​
170
​
171
​
172
​
173
​
174
// Unnamed Func
175
const dog = {
176
name: 'Digby'
177
};
178
​
179
const boundFunc = obj.unnamedFunc.bind(dog);
180
boundFunc(); // Digby
181
obj.unnamedFunc(); // Example Object
182
​
183
​
184
​
185
​
186
​
187
​
188
​
189
console.log('-------------------');
190
​
191
​
192
​
193
​
194
// Bind Time and Call Time Arguments
195
// bind time arguments passed in first, then call time arguments
196
function printAge(...args) {
197
const age = args[0];
198
const year = args[1];
199
console.log(args);
200
console.log(this.name + ' is ' + age + ' years old. Born in ' + year);
201
}
202
​
203
const otherArgs = [2005];
204
​
205
const printDigby = printAge.bind(dog, 12, ...otherArgs);
206
printDigby(2000);
207
printDigby(2008);
208
​
209
// const printRealDigby = printAge.bind(dog, 4);
210
// printRealDigby(2002);
Copied!
Last modified 2mo ago