-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathfunctions.js
More file actions
1201 lines (940 loc) · 61.5 KB
/
functions.js
File metadata and controls
1201 lines (940 loc) · 61.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
"use strict";
// TOPIC /////////////////////////////////////////////////////////////////////////////////////////////////////
// Functions (broad overview)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 1. What is a function?
// 2. What is functional programming?
// 3. What are the components of a function?
// 4. What is the difference between arguments and parameters?
// 5. What is a default parameter?
// 6. How do you define a function?
// + What is a function defintion?
// + What is a function expression?
// 7. How do you invoke a function?
// 8. How many ways are there to invoke a function?
// 9. How do you use functions in objects?
// 10. How do you invoke a function through a constructor?
// 11. How do you use prototypes?
// 12. How do you invoke through Call and Apply?
// 13. How do you use the arguments parameter?
// 14. Can you explain the return statement?
// 15. How do you use an anonymous closure (or self executing function)?
// 16. What is variable hoisting and scope?
// 17. How do you create and namespace modules?
// 18. How do you chain method calls?
// 19. What is a rest operator?
// 20. What is a callback function?
//
// NOTES ///////////////////////////////////////////////////////////////////////////////////////////////
// 1. Useful overview of information on functions taken from study, research, tutorials,
// mentor meetings, peer discussions, and good ole' fashioned curiosity. I've put the document in Question
// and Answer format for improved readability.
// 2. For more examples and rough idea for this page, see functionScratch.js
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
1. What is a function?
/////////////////////////
==SHORT ANSWER==
-- A function is a repeatable process or behavior.
==EXTENDED ANSWERS==
-- A function is a reusable recipe that perfoms the same set of actions over and over again on a set of ingredients
-- A function is a REPEATABLE (i.e. can be called multiple times) and DETERMINATE (i.e. predictable) PROCESS or BEHAVIOR.
-- A function is a series of STATEMENTS that are grouped into a special package.
-- A function is a MODULAR and fundamental BUILDING BLOCK of JavaScript that perform tasks or calculate values.
-- A function is an OBJECT that is a FIRST-CLASS ENTTITY which is treated as a VALUE.
==ANALOGY==
-- Think of a function as a resuable recipe for cooking.
-- That recipe (e.g. "function") performs the same set of actions (i.e. "main block" of function) over and over again on
a set of ingredients (e.g. parameters).
*/
/*
2. What is functional programming?
//////////////////////////////////
==SHORT ANSWER==
-- Functional programming is a PROGRAMMING STYLE/TECHNIQUE (i.e. PARADIGM) that breaks code into SINGLE-USE peices and focuses
on DATA-FLOW rather than control-flow.
==EXTENDED ANSWERS==
-- Functional programming stresses importance on the ORDER in which things run, specifically how the program progresses from
statement to statement, in-and-out of for loops and in-and-out of sub-routines.
-- Functional programming is about breaking your code into "verbs" (vs OOP which is about 'nouns').
-- In many ways, it is easier to think of the world in terms of nouns (and by extention objects).
-- So if we were to build a house in OOP, we would talk about the walls, doors, and windows.
-- However, with functional programming we are thinking about the ACTIONS.
-- So if we were building a house with functional programming, we would talk about turning the lights
on or off, opening or closing the doors, etc.
-- Functional programming uses many functions, passing functions to functions, returning functions, doing
things with the arguments and parameters.
==EXAMPLE==
Function Order What it does
_________________________________________________ ____________ ____________________________________
*/
function replaceIt(string) { // 3.1 Replaces the word 'this' with the word 'that'.
return string.replace("this", "that"); //
}
function capitalizeIt(string) { // 3.2 Capitalizes all the words in the string.
return string.toUpperCase(); //
}
function printIt(string) { // 3.3 Prints the string to console.
return console.log(string) //
}
function repAndCap(string) { // 2 ... we pass the string to repAndCap and executes
return printIt(capitalizeIt(replaceIt(string))); // in order by first running replaceIt, then capitalizing
} // it by running capitalizeIt, then finally printing it.
console.log(repAndCap("this is a test")) // 1 When repAndRap is called with the argument
// "this is a test"....
/*
3. What are the components of a function?
////////////////////////////////////////
==ANSWER==
-- A function is comprised of a function names "keyword", a name for that function (e.g. "myFunction"), a call signature with
parameters (which are stipulated or passed in), a main block of the function. The function is then called by calling the
function name as well as any parameters.
==EXAMPLE==
*/
// FUNCTION KEYWORD NAME CALL SIGNATURE (W/PARAMETER)
// \ | /
function myFunction(str) {
return str; //- MAIN BLOCK of function
}
console.log(myFunction("Hello!")); //- CALL (W/ARGUMENT)
/*
Component ID What it is and what it does
_________________ ___________ ________________________________________________________________________________________________
function > Keyword - Functions are `DEFINED` with the function keyword (regardless of how they are used or invoked).
- Defining a function is sometimes called "DECLARING" a function.
myFunction > NAME - The `NAME` of the code that can be invoked or called elsewhere in our code.
- Sometimesd the name can be `OPTIONAL`.
- You can use the following to name a function:
-- a to z (upper and lower case)
-- 0 to 9
-- _ (underscore)
-- $ (cash sign)
-- special characters
(str) > Parameters - `PARAMETERS` go inside the call signature parentheses (i.e. (...) ).
- Multiple parameters are seperated by commas (i.e. (num1, num2, num3) ).
- You can have as many parameters as you want.
- Parameters are variables that are local and ONLY available inside the function.
{...} > Main Block - Since the function has to do something, the main block of the function has a series of `INSTRUCTIONS`.
- Those instructions are called `STATEMENTS`.
- Statements go inside curly braces (i.e. {...} ).
- Statements are seperated by semicolons (i.e. ; ).
- Also remember NOT to add a semicolon after the main block (i.e. {}; )
console.log > Invoke - This invokes (or calls) the function to be used elsewhere in the code by name.
- console.log will print the result of the function to the browser console.
- myFunction("string") will call the function.
*/
/*
4. What is the difference between arguments and parameters?
//////////////////////////////////////////////////////////
==SHORT ANSWER==
-- Parameters are variables passed to the call signature while Arguments are values passed when the function in invoked.
==LONG ANSWER==
-- When you define a function (i.e. function declaration or function expression), you provide parameter "slots". When you
invoke the function, you pass in the values as arguments to fill those slots so the function has ingredients to efectively
"cook" the recipe in the function block of code.
==EXTENDED ANSWER==
-- When talking about functions, the terms parameters and arguments are often interchangeably used as if it were one and the
same thing but there is a very subtle difference.
A. Parameters are variables listed as a part of the function definition
-- i.e. function(num1, num2) {...} where num1 and num2 are the paramter
B. Arguments are values passed to the function when it is invoked
-- i.e. console.log(myFunction(1,2)) where 1 and 2 are the arguments.
-- Its important to know the difference because JavaScript does not throw an error if the number of arguments passed during a function
invocation are different than the number of parameters listed during function definition. This should make it clear that parameters
and arguments should be treated as two different entities.
*/
/*
5. What is a default parameter?
////////////////////////////////
==SHORT ANSWER==
-- A default parameter is a specified parameter that we put in the call signature parentheses of the function or in the code block.
==LONG ANSWER==
-- A default parameter can either be specified in a variable (i.e. let cake = ingredient || flour) or in the actual call signature of
the function itself, meaning that we do not need to pass anything in because that slot is filled with the information we need.
==EXAMPLES==
EXAMPLE WITHOUT DEFAULT PARAMETERS
==================================
-- below we have a normal function BEFORE default parameters:
*/
function interest(principal, rate, years) { // note here that no default parameters are given, only inputs.
return principal * rate / 100 * years;
}
console.log(`default parameter example before default:`);
console.log(interest(10000, 3.5, 5)); //-> 1750
/*
EXAMPLE WITH DEFAULT PARAMETERS IN VARIABLES USING 'OR'
=======================================================
-- However, we can use a variable to provide a default value with the or operator (i.e. ||).
-- note that you DO NOT instantiate the default parameters as variables.
*/
function interest2(principal, rate, years) {
rate = rate || 3.5; // the default parameter here is 3.5 (i.e. input OR 3.5 by default).
years = years || 5;
return principal * rate / 100 * years;
}
console.log(`default parameter example with default variable:`);
console.log(interest2(10000)); //-> 1750
/*
EXAMPLE WITH DEFAULT PARAMETERS IN THE CALL SIGNATURE
=====================================================
-- With ES6, you can do it in amuch cleaner way by inserting it inside the call signature itself.
-- Once you give a default parameter, every parameter after that should also have a default as well, otherwise
you get a NaN (not a number).
-- HOWEVER, if you pass in undefined (i.e. console.log(interest3(principle, rate = 3.5, undefined))), you will be able
to use default parameters at whichever point you wish... but try not to because it is not good practice.
*/
function interest3(principal, rate = 3.5, years = 5) { // note here default parameters are INSIDE the call signature.
return principal * rate / 100 * years;
}
console.log(`default parameter example with default variable in call signature:`);
console.log(interest3(10000)); //-> 1750
/*
6. How do you define a function?
////////////////////////////////
==SHORT ANSWER==
-- A function can be defined as either a function declaration or a function expression. Unlike function expressions which are NOT
hoisted (thus need to be placed where they are used), function declarations can be declared anywhere.
==EXTENDED ANSWERS==
What is a function Declaration?
===============================
-- A function declaration is hoisted with contents (hoisting is how the browser parses Javascript, reads through once
then executes second pass).
-- Function declarations are hoisted to the top of the top-level or if you have a function declaration inside
a function, to the top of that function.
-- With function declarations, you can use them above where they are declared.
*/
function addDeclaration(num1, num2) {
return num1 + num2;
}
console.log(`function declaration example:`)
console.log(addDeclaration(2,2)) //-> 4
/* What is a function expression?
==============================
-- Function expressions also go by the name "Definition Expression" and "Function literal".
-- Function expressions are a JavaScript pattern that lets you create a variable and execute it as a function.
-- Remember: a variable can be set to a number, a string, an object, or even a function (seen here).
-- Function expressions are Not hoisted with contents, but the reference to it may be hoisted if we assign it as a variable.
-- Functions defined as arguments to functions ARE expressions.
-- Internal functions with no names are also known as an anonymous function because you dont need a name for it.
-- Function expressions are useful because we can use it everywhere a variable can go.
-- Since a function expression is a variable (or if it is a const), we need to terminate the function with a semi-colon.
-- If you DO NOT have a name for the function (seen below), you have an ANONYMOUS function.
-- If you add a name to the function (i.e. let run = function walk() {...}), it is a NAMED function expression.
-- IMPORTANT: Because of an issue with hoisting, if you invoke a function expression before the function itself, you will get an error.
-- You can also run the function through another declared variable.
*/
// function expression:
let addExpression = function(num1, num2) {
return num1 + num2;
}; // note the semi-colon that terminates the variable.
console.log(`function expression example:`)
console.log(addExpression(3,3)); //-> 6
//function expression called through another variable:
let variableWithAddExpression = addExpression;
console.log(`function expression called via another variable:`);
variableWithAddExpression();
// ES6 Fat Arrow Function:
// -- when you read this, you would say 'goes to...' for fat arrow.
const addFatArrow = (num1, num2) => num1 + num2;
console.log(addFatArrow(4,4)) // 8
/*
7. How do you invoke a function?
/////////////////////////////////
==SHORT ANSWER==
-- You can invoke a function most commonly using the function name (i.e. myFunction) and passing in the ARGUMENTS in the call signature
which occupy specific slots that translate to the function being called.
==EXAMPLES==
-- In the following example, we will see how to invoke the function and pass the arguments as parameters.
*/
function multiplyIt(num1, num2) { // function
return num1 * num2;
}
console.log(`multiply it result`);
console.log(multiplyIt(2, 3)); //=>6 // invocation (note that console.log is just so that the example prints to console)
/* -- In the example above, we have two specific components: the function and the invocation.
-- The function (i.e. multiplyIt) is a basic function declaration with two parameters, num1 and num2.
-- The objective of the function is to multiply num1 and num2 together and return the result.
-- To invoke the multiplyIt function, we simply CALL the function name AND pass in any parameters we need.
Function name first argument
\ |
multiplyIt( 2, 3 )
/ \
call signature second argument
-- It is important to note that when you pass arguments to the function, those are dedicated "SLOTS" for those arguments.
-- So in the multiplyIt example, we're passing two arguments:
-- when we pass "2" as an argument, it fills the FIRST"slot" as num1.
-- when we pass "3" as an argument, it fills the SECOND slot as num2.
slot 1 slot 2
_\__ __/_
| | | |
multiplyIt( 2, 3 )
| |
| |
function multiplyIt(num1, num2) {
return num1 * num2;
} | |
2 3 => 6
-- So this means that num1 will ALWAYS be 2 when the function is invoked as it was above.
-- And num1 will ALWAYS have the value of 2 inside the function body.
*/
/*
8. How many ways are there to invoke a function?
/////////////////////////////////////////////
==SHORT ANSWER==
-- You can invoke a function most commonly by function (e.g. functional programming) and method (e.g. methods in objects).
Constructors and call and apply methods
==LONG ANSWER==
-- There are 4 ways to invoke a function:
1. Invoke as a function.
2. Invoke as a method.
3. Invoke as a constructor.
4. Invoke with call and apply methods.
-- Invoking as a FUNCTION and METHOD are the most common.
-- functions also get a few extra parameters, like arguments and THIS.
-- IMPORTANT: A property of functions is that invoking them passes control of the program to the function we are calling.
==EXAMPLE==
-- A common way to invoke a function is TRADITIONAL INVOCATION.
-- so if a function has a name, you can call it by its name and pass along 0 to as many parameters as you need (i.e. myFunction(a,b,c); ).
*/
function addItUp(num1, num2) { // plus is passed two parameters, a and b.
return ( // return is used as a function (return IS a function so it can be passed parameters).
console.log(num1 + num2), // here we have num1 + num2, which the result of our operation. NOTE THE COMMA!
console.log(num1 * num2), // here we have num1 * num2, which is another result of our operation. NOTE THE COMMA!!
console.log(arguments) // here we pass the `arguments` parameter (this will restate our parameters).
); // Thus everything above is a straight function call.
}
console.log(`results of Return as function example below`);
addItUp(2, 3); // now we INVOKE the function and PASS the parameters we want. We have two slots, so two numbers.
//-> 5
// 6
// { '0': 2, '1': 3 }
/*
9. How do you use functions as objects?
//////////////////////////////////////
==SHORT ANSWER==
-- A function method is a property with a function assigned as its value, and invoked using dot notation.
==LONG ANSWER==
-- in addition ot calling functions using the Traditional way (i.e. call name and pass along parameters), we can also invoke them by METHODS.
-- A METHOD is a function that has been assigned as a property of an OBJECT (i.e. myObject.firstName where .firstName is the method).
-- An OBJECT is a complex data type that brings together properties and behaviors into a single entity.
-- An OBJECT always begins and ends with curly braces.
-- Inside an object, we have key:value pairs.
-- An OBJECT can have:
-- variables -- (i.e. let car = "Honda"; ).
-- lists (aka arrays) -- (i.e. let cars = ["Toyota", "BMW", "Mercedes"]; ).
-- any data type (including other objects).
-- The example below is a normal function with key/value pairs:
*/
let info = {
firstName : 'John', // a name/value pair
lastName : 'Smith',
occupation : 'soldier'
}
console.log(`result of normal function test:`)
console.log(info.firstName); //-> John ()
/*
-- The example below shows a function as a property of an object
-- Here we create an object called 'report' and add 2 properties, status and a method called plus (which is function).
*/
let report = {
status: 'Awesome', // property called status with a value called Awesome. NOTE COMMA!
plus: function(a,b) { // this is an anonymous function assigned to an element. It is called with the 'plus' identifier
return (
console.log(this), // check the value of the `this` attribute.
console.log(a + b), // return result of the function.
console.log(arguments), // find out what the arguments are (i.e. values of a and b).
console.log(this.status) // ask for the `this` attribute and then ask for the status variable.
);
}
}
console.log(`results of function in object example:`)
report.plus(2,3); //-> { status: 'Awesome', plus: [Function: plus] }
// 5
// { '0': 2, '1': 3 }
// Awesome
/*
10. How do you invoke a function through a constructor?
/////////////////////////////////////////////////////
-- functions can construct objects as well.
-- in other words, the function itself BECOMES the constructor.
-- you can create an object with the `new` keyword.
-- this method of creating an object is called a CONSTRUCTOR INVOCATION.
-- a constructor builds on object based on the original function
-- each instance will have its own set of properties (see example below).
-- A CONSTRUCTOR INVOCATION can use the function keyword to create an object with the variable from the function.
-- By convention, constructor functions should always be CAPITALIZED.
IMPORTANT NOTE: This does not seem to work correctly in VSCode, but in chrome it does.
1. So first we create a function.
-- "dog" is essentially an object.
-- this dog function only had 2 variables, name and breed.
var Dog = function() {
var name, breed;
console.dir(this);
}
2. Next, we'll create a new instance of this with a new constructor.
-- this creates a new object based on the `dog` function.
-- the NEW keyword create a new instance of the object (like a copy or reproduction).
creates "new" object
\
firstDog = new Dog;
3. Now that the new object has been created, we can assign a name and a breed.
firstDog.name = "bowser";
firstDog.breed = "Yorkie";
4. Now you can ask for the dogs first name.
console.log(firstDog); //-> dog {name: "bowser", breed: "yorkie"}
*/
/*
11. How do you expand objects through prototypes?
///////////////////////////////////////////////
-- JavaScript is known as a prototypal inheritance langauge, which means you can base the functionality of an
object on ANOTHER object,
-- EVERY object in JavaScript can be based on another object.
-- With the prototype object create relationships in JavaScript and we can expand anything in JavaScript.
- this is convienent because we dont have to build the same functionality for different things.
- the way this is done is by linking the prototype object to another. For example:
1. First, we create out constructor function for 'Dog' and create a dog (i.e. firstDog).
let Dog = function() {
let name, breed;
}
firstDog = new Dog;
firstDog.name = 'bowser';
firstDog.breed = 'collie'
2. To add functionality to the Dog obejct. For this example, we'll create a function called 'speak'.
let speak = function(sayWhat) {
console.log(sayWhat);
}
3. To expand on Dog by accessing on its prototype and setting a method of Dog to be the same as the speak function.
Dog.prototype.speak = speak;
- what this does is give a Dog the ability (or method) to speak.
4. then we attach the speak method to firstDog and pass along something to say.
firstDog.speak('I go bark sometimes')
*/
/*
12. How do you invoke through Call & Apply?
/////////////////////////////////////////
-- Call & Apply is sometimes refered to as "indirect invocation".
-- Call & Apply can define the value of `this` argument.
-- Call & Apply can control `this` and `arguments`.
-- Call passes a VALUE.
-- APPLY passes an ARRAY.
*/
let talk = function() {
console.log(this.loud);
}
let talkOutLoud = {normal: "whisper", loud: "yell"}
talk.call(talkOutLoud); //-> yell
// we invoke the function call...
// use the .call method...
// pass-in the talkOutLoud
// console.log runs this(i.e. talk) dot loud(from talkOutLoud)
// Another way to do the same thing above is like this:
let talk2 = function(what) {
console.log(what);
}
let talkOutLoud2 = {normal: "whisper", loud: "yell"}
talk2.call(talkOutLoud2, talkOutLoud2.normal); //-> whisper
// normal is being passed into the what variable in the function.
// which is then passed into the console.log.
/*
-- Now the difference between call and apply is that apply can pass an ARRAY.
*/ let talk3 = function(what) {
console.log(what);
}
let talkOutLoud3 = {normal: "whisper", loud: "yell"}
talk3.apply(talkOutLoud3, ['roar']); //-> roar
// instead of normal (previous), we pass in an array with 'roar'.
// we change call to apply...
// roar is passed to the what variable and the console.log.
/*
13. What is the arguments parameter?
///////////////////////////////
-- Although we've been passing elements to functions, but often we dont know how many elements we will be needing.
-- You want your function to be able to accept an number of elements.
-- The ARGUMENTS PARAMETER is used to hold a list of all the elements passed as arguments to the function.
-- The arguments parameter is an array-like object becasue it looks like an array and we can do some things we do to arrays.
-- for example, we can call the numerical index(i.e. arguments[x] ).
-- we can also get the arguments.length (i.e. the amount of elements we pass to the function).
-- because we have these properties, we can loop through the arguments with a for-loop.
-- however, we CANNOT use array methods (i.e. pop, push, shift, etc. ).
*/
let addSomething = function() {
let sum = 0; // sum initialized to 0.
for (let i=arguments.length - 1; i >= 0; i--) { // for-loop will go through all the arguments in the arguments array
sum += arguments[i]; // increment the arguments so they add themselves together.
}
return sum;
}
console.log(addSomething(4,4,4)); //-> 12 // because we use `arguments`, we can pass in as many
console.log(addSomething(5,5,5,5,5,5,5,5)); //-> 40 // arguments as we want.
/*
- To pass as many arguments as we want (and in this case get the sum), we use the special object called object again.
*/
function addSomething2() {
let total = 0;
for (let value of arguments) {
total += value;
}
return total;
}
console.log(`example with arguments object:`)
console.log(addSomething2(1,2,3,4,5,10)); //-> 25
/*
14. Can you explain the return statement?
////////////////////////////////////////
-- When you invoke a function, its like generating an equation, which usually have results.
-- The 'RETURN' statement can return a result, object, or even another function.
-- This lets JavaScript do things that are very difficult in other languages.
-- In fact, `RETURN` is a function in its own right and you can return a series of parameters in
the parentheses (i.e. return (...) ). For example:
function example(a,b) {
return (
console.log(a + b),
console.log(a - b),
console.log(a * b)
);
}
-- So to put it simply, the return statement expresses the result of the operation we perform in our function.
-- For example:
*/
let addTheThing = function(a,b) {
return a + b; // the job of the return function here is to return the result of a + b.
}
console.log(addTheThing(4,5)) //-> 9
/*
-- the return statement is optional. that is to say, if you do not include it in your code, the function will return something.
-- the return statement is only in the function body.
-- the return statement can be used to return something back to the caller.
-- so you could assign it to a variable and it will place a value in the variable when the function returns.
-- the return statement is usually the last statement in a function (stops execution).
-- the return statement can be anything or return nothing.
-- the return statement appears only in the body of a function (otherwise it is a syntactical error).
*/
/*
15. How do you use an anonymous closure (or self executing function)?
//////////////////////////////////////////////////////////////////////
-- a typical function definition can be invoked by calling the function name anywhere in the code. For example:
*/
let cat = function() {
console.log('meow')
}
console.log(cat());
/*
-- However, there is a way to invoke a function and NOT call it manually.
-- Anonymous closures can be used to invoke a function automatically by adding parentheses AFTER the function body.
-- Anonymous closures DO NOT have a name... they dont need it since they run automatically.
-- Any variables INSIDE the function body will NOT be known outside the anonymous closure.
-- the () at the end of the function change the function declaration to a function expression.
-- when you use the function keyword, JavaScript assumes you want to create a function with a name. But it will not run it.
--
*/
let cat2 = function() {
console.log('meow meow')
}();
/*
-- You can also instantiate the function by passing parameters into those parentheses.
*/
let addTheCats = function(message) { // Second, the string is passed (via message) to the function.
console.log(message); // Third, the string finally is passed to the console.log statement.
}("Good evening, I am a cat"); // First, a string is passed.
/*
-- You can also make the function completely anaonymous.
-- You make a function completely anonymous by wrapping the ENTIRE function in parentheses.
-- what this does is ask JavaScript to comvert this function into a value and then use the last set of parentheses to
pass in any parameters (if needed).
-- important to remember, you dont need to have any parameters in the last parentheses, just that this example has one.
*/
(function(message) {
console.log(message)
})("I am an anonymous function");
/*
16. What is variable hoisting and scope?
///////////////////////////////////////
-- HOISTING is the process of moving the FUNCTION DECLARATIONS to the top of the file automatically.
-- HOISTING refers to how browsers parse JavaScript.
-- First pass, the browser reads through the code once, setting aside space for variables, functions, etc.
-- Second pass, the browser reads through AGAIN and executes the code.
-- this is how the browser knows what is what.
-- With hoisting, we can call a FUNCTION before it has been defined.
-- i.e. function hoistThis() {...}
-- However, we CANNOT call a function that is defined using FUNCTION EXPRESSION syntax.
-- this is because when the JavaScript engine executes the code, it moves all the function DECLARATIONS to the top.
-- when all the function declarations are 'HOISTED' to the top, we get the term 'hoisting',
--i.e. const hoistThis = function() {...}
-- VARIABLE SCOPE defines how the variables declared CAN or CANNOT be accessed at different places in your code.
-- GLOBAL SCOPE means that the variable is available EVERYWHERE in the code.
-- BLOCK (LOCAL) SCOPE means that the variable is only available within the confines of the function.
-- SCOPE CHAIN refers to the way the JavaScript interpreter determines the value of a variable.
-- first, the interpreter looks locally for the variable.
-- if it is not there, then the interpreter will look UP THE SCOPE CHAIN until it reaches GLOBAL SCOPE.
-- VARIABLE SHADOWING means that if there is a global AND block scope variable, the local block variable will take precedence.
-- GLOBAL variables have some negative attributes.
-- GLOBALS tend to have unintended SIDE EFFECTS.
-- SIDE EFFECTS occur when a local scope variable reaches into global and changes a value there.
-- Side Effects are UNINTENDED since it can change an outside variable to carry out its instructions.
-- When this happens, a code is INDETERMINATE.
-- A function should be DETERMINATE, meaning that it should always return the same value and have NO side effects.
-- A function that is determinate is a PURE function.
*/
/*
17. How do you create and namespace modules?
///////////////////////////////////////
-- modules let you reuse code across apps.
-- when you just start coding, you are coding just for that program. However, when you start a new project you
might tend to look around your old code to find bits and peices to use.
-- modules will allow you to start reusing those bits and peices without having to capy-and-paste.
-- in a way, modules is like creating a library for you to use on any project.
-- To create a module, you need to create a NAME SPACE.
-- namespacing allows you to protect variables that you have in your modules from any global scoped variables.
-- this is important because you might have variables in your module that are in the application.
-- so we know we can create a self executing function (within parentheses) which protects all the variables inside from global scope.
-- but what if we want access to those variables OUTSIDE the closure but INSIDE our application?
-- to do this, we need to create a variable and assign it to our self executing function.
*/
let myLibraryDemo = (function() {
let myBook = "Moby Dick";
})(); //->
/*
-- inside the function we have a private variable (i.e. myBook).
-- the variables in this function would NOT be accessible outside the function (i.e. protected from global scope).
-- Now if you want to access a variable from OUTSIDE the function, you need a RETURN statement to commicate back with the
rest of the application.
*/
let myLibrary = (function() {
return { // Here we return an object.
book: function() { // Then, we have an element with the name 'book' and a method (i.e. function).
console.log('Pride and Prejudice')
}
}
})();
myLibrary.book(); //-> Moby Dick // call function with name space (i.e. myLibrary) and method (i.e. book).
/*
-- main thing is that the name space protects the variables inside from global scope.
-- So what we've done is create a module and used name spacing to protect that module's internal variables from global scope.
*/
/*
-- What if we want to send infromation TO our function using an object and how to set defaults just in case the user calls a method without
initializing it?
-- To send information, we use an object.
-- it s good to use an object because we can pass in multiple key/value pairs to the function and then parse each of the values out.
*/
let myLibrary2 = (function() {
return {
bookCollection: function() {
console.log(arguments[0].book); // Capture the argument as arguments[0] (i.e. the 0th argument)
}
}
})();
myLibrary2.bookCollection({ book: 'Jane Eyre'}); //-> Jabe Eyre
/*
-- but suppose you forget to initialize the bookCollection function?
-- you will get an error because its asking to read an argument with nothing in it.
-- To fix this, we need to do a SHORT CIRCUIT EVALUATION.
*/
let myLibrary3 = (function() {
return {
bookCollection: function() {
let myArguments = arguments[0] || ''; // so here if the user forgets to set the argument, myArguments will be set to nothing.
let statement = myArguments.book || 'nothing'; // this is setup to only be the `say` parameter... but if it is empty, then it says 'nothing'.
console.log(statement);
}
}
})();
myLibrary3.bookCollection(); //-> nothing // because no arguments are given, you will get 'nothing'.
myLibrary3.bookCollection({ book: 'Persuasion'}); //-> Persuasion // because we now have a key value pair.
/*
-- Now what if we have a bunch of variables everywhere within a much larger function?
-- it would NOT be efficient to have these values scattered all over the place.
-- To avoid this, we need a DEFAULT OBJECT for the function.
*/
let myLibrary4 = (function() {
let DEFAULT = {
book: 'Northanger Abbey' // 2. this is good if you need to modify your defaults in one place.
}
return {
bookCollection: function() {
let myArguments = arguments[0] || '';
let statement = myArguments.book || DEFAULT.book; // 1. instead of inserting the default value here, you can relocate to a seperate variable.
console.log(statement);
}
}
})();
myLibrary4.bookCollection();
/*
18. How do you chain method calls?
/////////////////////////////////
-- CHAINING makes it easy to work with multiple methods and it allows one function to call another.
-- similar to jQuery.
*/
let cars = (function() {
let DEFAULT = {
car: 'Ferrari',
speed: 'normal'
}
return {
carCollection: function() {
let myArguments = arguments[0] || '';
let statement = myArguments.car || DEFAULT.car;
console.log(statement);
}, // 1. add another item to our object (i.e. run).
run: function() {
let myArguments = arguments[0] || '';
let running = myArguments.speed || DEFAULT.speed; // 2. running is either the argument or default (in DEFAULT).
console.log(`running...` + running); // 3. output will be running plus either argument OR default.
}
}
})();
cars.carCollection(); //-> Ferrari
cars.run(); //-> speed...normal
cars.run( { speed: 'fast'}); //-> speed...fast
/*
-- Now you can use DOT NOTATION to chain one call to another.
-- However, you need to understand WHY it is working.
-- what is important is we have to make sure each function returns the calling object... which is exactly what the `this` argument does,
specifically, return the object that contains it.
-- why is this working? The `this` parameter is goign to return the instance of the object.
-- in other words, in the example below the `this` is going to return the cars2 object.
-- normally return would exit the current function, but in this case the `this` returns the carCollection (or run) and returns the
cars2 object where you have access to carCollection AND run.
*/
let cars2 = (function() {
let DEFAULT = {
car: 'Ferrari',
speed: 'normal'
}
return {
carCollection: function() {
let myArguments = arguments[0] || '';
let statement = myArguments.car || DEFAULT.car;
console.log(statement);
return this;
},
run: function() {
let myArguments = arguments[0] || '';
let running = myArguments.speed || DEFAULT.speed;
console.log(`running...` + running);
return this;
}
}
})();
cars2.carCollection({ car: 'Porsche'}).run({ speed: 'Super Fast'});
/*
19. What is a Rest Operator?
////////////////////////////
-- if you want a function with varying numbers of parameters, you can use the rest operator.
-- this is not to be confused with the spread operator because it is used with arrays.
-- with a spread operator, we can spread an array which means take it individual elements.
-- but when we use the ... along with a parameter of a function, it is refered to as a spread operator.
-- when you apply the rest operator to a parameter of a function, we pass a varying number of arguments and the rest
operator will take all of them and put them in an array.
-- remember, rest operator must be LAST formal parameter (i.e. function sum(var1, var2, ...var3) {...}).
-- because it is always at the end, we have as many parameters as we want but we use the ... for the REST of the parameters.
*/
// classic was of getting the sum with rest operator
function sum1(...args) {
let total = 0;
for (let value of arguments) {
total += value;
}
return total;
}
console.log(sum1(1,2,3,4,5,10));
// more modern way of getting the sum with rest operator
function sum2(...args) {
return args.reduce((a, b) => a + b);
}
console.log(sum2(1,2,3,4,5,10));
// more complex example
function sum3(discount, ...prices) {
const total = prices.reduce((a,b) => a + b);
return total * (1 - discount); // if dicount is .01 subtracted from 1 is 0.9 multiplied by total will...
} // ...return final price after discount.
console.log(sum3(0.1, 20, 30)); // 0.1 is the discount, 20 and 30 are the prices.
//-> 45
/*
20. What is a callback?
//////////////////////
-- A callback is a function that is passed into another function as a parameter to another function.
-- for example, if you run a .forEach on an array (i.e. something.forEach(function(key) {return `${key}`})), where we pass in
"function" is a callback.
-- Note that that .forEach example is not asynchronous.
-- A callback is a convention in JavaScript that is often used with asyncronous programming.
-- A callback is used when you want to do things asyncronously, or whenever you want to exectue a code, which may not necessarily be
in order, but at a certain point in time, or when an event takes place.
-- A callback often uses the anonymous functions (i.e. functions without names like function() {...}) because they are
evoked immediately once the the event takes place.
-- A callback is often tied to events (i.e. to take care of tasks whenever an event is triggered).
-- callbacks are also called "higher order functions".
-- callbacks are a way to make sure certain code doesnt execute until other code has already finished execution.
-- when you pass a function as an argument.
-- a callback is a name to describe a method that is supplied as an argument to another method such that when the parent method is
called and the method body completes, the callback function is THEN invoked.
-- in javascript, functions are objects, so functions can be taken as arguments and can be returned by other functions.
-- any function that is passed as an argument is called a callback function.
*/
/*
EXAMPLE 1: Basic example
========================
-- In the example below, we have two functions: xS and yS.
-- However, even through we have xS as an argument, it does not log in the console. Why?
-- When we pass xS into yS, we essentially want to pass it in as an argument so that it will run after we call yS.
-- But because theres no enforced order of operations, only yS will print.
*/
let xS = function() {