├── .gitignore
├── CodeWars
├── app.js
├── app2.js
├── app3.js
├── app4.js
├── app5.js
└── index.html
├── Greetr
├── Greetr.js
├── app.js
└── index.html
├── README.md
├── gitignore
└── greetr.js
/.gitignore:
--------------------------------------------------------------------------------
1 | Code/
--------------------------------------------------------------------------------
/CodeWars/app.js:
--------------------------------------------------------------------------------
1 | String.prototype.toJadenCase = function () {
2 | return this
3 | .split(" ")
4 | .map(function(w){return w[0].toUpperCase() + w.slice(1);})
5 | .join(" ")
6 | ;
7 | };
8 |
9 | function makeString(s){
10 | return s
11 | .split(" ")
12 | .map(function(w){return w[0];})
13 | .join("")
14 | ;
15 | //const makeString = s => s.split(' ').map(v => v.charAt(0)).join('');
16 | // return (s.match(/\b\w/g)).join('');
17 | }
18 |
19 |
20 | var str = "How can mirrors be real if our eyes aren't real";
21 | var str2 = "sees eyes xray yoat";
22 |
23 | console.log(makeString(str2));
24 |
25 | function calculator(distance, busDrive, busWalk) {
26 | var walk = 5
27 | var bus = 8
28 | // switch(expression) {
29 | // case n:
30 | // code block
31 | // break;
32 | // case n:
33 | // code block
34 | // break;
35 | // default:
36 | // default code block
37 | // }
38 | }
39 |
40 | function minutes(distance, speed){
41 | return distance * speed
42 | }
43 |
44 |
45 |
--------------------------------------------------------------------------------
/CodeWars/app2.js:
--------------------------------------------------------------------------------
1 | function minutes(distance, speed){
2 | return (distance * 60) / speed ;
3 | }
4 | function calculator(distance, busDrive, busWalk) {
5 | var walkMinutes = minutes(distance,walk)
6 | var busMinutes = minutes(busDrive,bus) + minutes(busWalk,walk)
7 | var difference = busMinutes - walkMinutes
8 | if (walkMinutes < 10)
9 | return "Walk";
10 | else if (walkMinutes > 120 && busMinutes > 120)
11 | return "Bus";
12 | else if ( difference >= 0 )
13 | return "Walk";
14 | else if (difference < 0)
15 | return "Bus";
16 | }
17 |
18 |
19 | // calculator(5, 6, 1)
20 | // calculator(4, 5, 1)
21 | // calculator(5, 8, 0)
22 | // calculator(5, 4, 3)
23 | // calculator(11, 15, 2)
24 | // calculator(0.6, 0.4, 0)
25 | // calculator(10, 0.4, 0)
26 |
--------------------------------------------------------------------------------
/CodeWars/app3.js:
--------------------------------------------------------------------------------
1 | vocals = new Set(['a', 'e', 'i' , 'o', 'u' , 'ä' , 'ö' , 'ü'])
2 |
3 | function isVocal(value) {
4 | return vocals.has(value)
5 | }
6 |
7 | function derDieDas(wort){
8 | var len = wort.toLowerCase().split('').filter(isVocal).length
9 | return (len < 2 ? 'das ' : len <= 3 ? 'die ' : 'der ') + wort;
10 | }
11 | function derDieDas2(wort){
12 | var len = wort.match(/([aeiouäöü])/gi).length
13 | return (len < 2 ? 'das ' : len <= 3 ? 'die ' : 'der ') + wort;
14 | }
15 |
16 |
17 | //§derDieDas('Knödel')
--------------------------------------------------------------------------------
/CodeWars/app4.js:
--------------------------------------------------------------------------------
1 | function Node(data) {
2 | this.data = data;
3 | this.next = null;
4 | }
5 |
6 | function push(head, data) {
7 | var node = new Node(data)
8 | node.next = head;
9 | return node;
10 | }
11 |
12 | function pop(head) {
13 | node.next = null;
14 | return head.data;
15 | }
16 |
17 |
18 | function buildOneTwoThree() {
19 | var node = new Node(3)
20 | node = push(node,2);
21 | node = push(node,1);
22 | return node;
23 | }
24 | ///
25 | function push(head, data) {
26 | return new Node(data, head);
27 | }
28 |
29 | function buildOneTwoThree() {
30 | return [3, 2, 1].reduce( (head, data) => push(head, data), null );
31 | }
32 |
33 | function Node(data, next = null) {
34 | this.data = data;
35 | this.next = next;
36 | }
--------------------------------------------------------------------------------
/CodeWars/app5.js:
--------------------------------------------------------------------------------
1 | function Node(data) {
2 | this.data = data;
3 | this.next = null;
4 | }
5 | function NodeToArray(head){
6 | if (head == null)
7 | return [0]
8 | var next = head.next
9 | var arr =[head.data]
10 | while (next!=null){
11 | arr.push(next.data)
12 | next = next.next
13 | }
14 | return arr
15 | }
16 |
17 | function length(head) {
18 | return NodeToArray(head).reduce(function(previousValue, currentValue, currentIndex, array) {
19 | return currentIndex;
20 | });
21 |
22 | }
23 |
24 | Implement Length() to count the number of nodes in a linked list.
25 |
26 | length(null) === 0
27 | length(1 -> 2 -> 3 -> null) === 3
28 | Implement Count() to count the occurrences of an integer in a linked list.
29 |
30 | count(null, 1) === 0
31 | count(1 -> 2 -> 3 -> null, 1) === 1
32 | count(1 -> 1 -> 1 -> 2 -> 2 -> 2 -> 2 -> 3 -> 3 -> null, 2) === 4
33 | I've decided to bundle these two functions within the same Kata since they are both very similar.
34 |
35 | The push() and buildOneTwoThree() functions do not need to be redefined.
--------------------------------------------------------------------------------
/CodeWars/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Greetr/Greetr.js:
--------------------------------------------------------------------------------
1 | // IEFF needs the global object and the jQuery reference
2 | ;(function(global, $) {
3 |
4 | var Greetr = function(firstName, lastName, language){
5 | // Create a new Function Constructor which has the same parameters as the called
6 | // one from the client, but we return a new Object. The new object is created
7 | // because we call 'new' to a Function Constructor
8 | return new Greetr.init(firstName, lastName, language);
9 | }
10 |
11 | // No access is possible here from outside the lobrarys
12 | var supportedLangs = ['en', 'es'];
13 |
14 | // Declaring and creating new variables that are not expose outside
15 | var greetings = {
16 | en:'Hello',
17 | es:'Hola'
18 | };
19 |
20 | var formalGreetings = {
21 | en:'Greetings',
22 | es:'Saludos'
23 | };
24 |
25 | var logMessages = {
26 | en:'Logged in',
27 | es:'Sesion iniciada'
28 | };
29 |
30 | Greetr.prototype = {
31 | // Exposed functions
32 | fullName: function() {
33 | return this.firstName +' '+ this.lastName;
34 | },
35 |
36 | validate: function(){
37 | if( supportedLangs.indexOf(this.language)==-1 ){
38 | throw "Invalid language"
39 | }
40 | },
41 |
42 | greeting: function(){
43 | return greetings[this.language] + ' ' + this.firstName + '!';
44 | },
45 |
46 | formalGreeting: function(){
47 | return formalGreetings[this.language] + ', ' + this.fullName();
48 | },
49 |
50 | greet: function(formal) {
51 | var msg;
52 |
53 | // if undefined or null it will be coerced to 'false'
54 | if (formal) {
55 | msg = this.formalGreeting();
56 | }
57 | else {
58 | msg = this.greeting();
59 | }
60 |
61 | if (console) {
62 | console.log(msg);
63 | }
64 |
65 | // 'this' refers to the calling object at execution time
66 | // makes the method chainable
67 | return this;
68 | },
69 |
70 | log: function() {
71 | if (console) {
72 | console.log(logMessages[this.language] + ': ' + this.fullName());
73 | }
74 | return this;
75 | },
76 |
77 | setLang: function(lang) {
78 | this.language = lang;
79 | this.validate();
80 | return this;
81 | },
82 |
83 | HTMLgreeting: function(selector, formal){
84 | if(!$){
85 | throw 'jQuery not loaded';
86 | }
87 | if(!selector){
88 | throw 'Missing jQuery selector'
89 | }
90 |
91 | var msg;
92 | if (formal) {
93 | msg = this.formalGreeting();
94 | }
95 | else {
96 | msg = this.greeting();
97 | }
98 | $(selector).html(msg);
99 | return this;
100 | }
101 |
102 | };
103 |
104 | Greetr.init = function(firstName, lastName, language){
105 | // Keep 'this' safe to the future calls. We will always have this object in 'self'
106 | var self = this;
107 | // Default values
108 | self.firstName = firstName || '';
109 | self.lastName = lastName || '';
110 | self.language = language || "en"
111 |
112 | self.validate()
113 | }
114 |
115 | // 'Greetr.init.prototype' is the prototype of the init function. Every function
116 | // '.prototype' is where the prototype is. We wnat that our object prototype is
117 | // 'Greetr.prototype' that we will define ourself.
118 | // That way we point 'Greetr.init.prototype' to 'Greetr.prototype'.
119 | Greetr.init.prototype = Greetr.prototype;
120 |
121 | //Attach it to the global object to be accessed everywhere and Alias to G$
122 | global.Greetr = global.G$ = Greetr;
123 |
124 |
125 | }(window, jQuery)); // we call teh function with the window(global) object and the jQuery reference
--------------------------------------------------------------------------------
/Greetr/app.js:
--------------------------------------------------------------------------------
1 | $('#login').click(function(){
2 | var userGreeter = G$('John', 'Doe');
3 | userGreeter.setLang($('#lang').val()).HTMLgreeting("#greeting",true).log();
4 | })
5 |
--------------------------------------------------------------------------------
/Greetr/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Table of Contents
2 | - [Table of Contents](#table-of-content)
3 | - [General Concepts](#general-concepts)
4 | - [Syntax parsers](#syntax-parsers)
5 | - [Lexical environments](#lexical-environments)
6 | - [Execution contexts](#execution-contexts)
7 | - [Name/Value pair](#namevalue-pair)
8 | - [Object](#object)
9 | - [Global Environment and The Global Object](#global-environment-and-the-global-object)
10 | - [Execution Context](#execution-context)
11 | - [Creation Phase:](#creation-phase)
12 | - [Execution Phase](#execution-phase)
13 | - [Single Threaded Synchronous Execution](#single-threaded-synchronous-execution)
14 | - [Function invocation](#function-invocation)
15 | - [Execution Stack](#execution-stack)
16 | - [Variable environments.](#variable-environments)
17 | - [Scope Chain](#scope-chain)
18 | - [Scope](#scope)
19 | - [ES6 let](#es6-let)
20 | - [Asynchronous](#asynchronous)
21 | - [3 Types and Operators](#3-types-and-operators)
22 | - [Dynamic Typing](#dynamic-typing)
23 | - [Primitive Types](#primitive-types)
24 | - [Operators](#operators)
25 | - [Precedence and Associativity](#precedence-and-associativity)
26 | - [Coercion](#coercion)
27 | - [Comparison Operators](#comparison-operators)
28 | - [Default values](#default-values)
29 | - [Objects and Functions](#objects-and-functions)
30 | - [Objects and Dots](#objects-and-dots)
31 | - [Object literals](#object-literals)
32 | - [NameSpace](#namespace)
33 | - [JSON and Object literals](#json-and-object-literals)
34 | - [Functions and Objects](#functions-and-objects)
35 | - [Function Statements and Expression](#function-statements-and-expression)
36 | - [By Value vs. by Reference](#by-value-vs-by-reference)
37 | - [Objects, Functions and 'this'](#objects-functions-and-this)
38 | - [Arrays](#arrays)
39 | - ['arguments' and SPREAD](#arguments-and-spread)
40 | - [Overloading](#overloading)
41 | - [Automatic semicolon insertion](#automatic-semicolon-insertion)
42 | - [Immediately Invoked Functions Expressions (IIFEs)](#immediately-invoked-functions-expressions-iifes)
43 | - [IIFE and Safe code](#iife-and-safe-code)
44 | - [Closures](#closures)
45 | - [Function Factories](#function-factories)
46 | - [Callback function](#callback-function)
47 | - [Function](#function)
48 | - [Function borrowing](#function-borrowing)
49 | - [Function currying](#function-currying)
50 | - [Functional programming](#functional-programming)
51 | - [Udnerscore.js](#udnerscorejs)
52 | - [Object Oriented JavaScript Prototypal Inheritance](#object-oriented-javascript-prototypal-inheritance)
53 | - [Inheritance](#inheritance)
54 | - [Classical Inheritance](#classical-inheritance)
55 | - [Prototypal Inheritance](#prototypal-inheritance)
56 | - [Reflection](#reflection)
57 | - [Building Objects](#building-objects)
58 | - [_new_](#new)
59 | - [Function constructors and Prototypes](#function-constructors-and-prototypes)
60 | - [Built in Function Constructor](#built-in-function-constructor)
61 | - [Arrays and for..in](#arrays-and-forin)
62 | - [_Object.create_ and Pure prototypal inheritance](#objectcreate-and-pure-prototypal-inheritance)
63 | - [Polyfill](#polyfill)
64 | - [ES6 and Classes](#es6-and-classes)
65 | - [_typeof_ and _instanceof_](#typeof-and-instanceof)
66 | - [Strict Mode](#strict-mode)
67 | - [Method Chaining](#method-chaining)
68 | - [Own Libraries architect as jQuery](#own-libraries-architect-as-jquery)
69 | - [Greetr](#greetr)
70 | - [Bonus](#bonus)
71 | - [Transpile](#transpile)
72 |
73 |
74 | # General Concepts
75 | ## Syntax parsers
76 | A program that reads your code and determine what it does and if its grammar is correct.
77 |
78 | ## Lexical environments
79 | Where something sits physically in the code you write.
80 |
81 | Place where the parts of your code sits, is important.
82 |
83 | ## Execution contexts
84 | A wrapper to help manage the code that is running.
85 |
86 |
87 | ## Name/Value pair
88 | A name which maps to a unique value
89 | ```javascript
90 |
91 | Address: '100 main str'
92 | ```
93 |
94 | ## Object
95 | A collection of name value pairs.
96 | ```javascript
97 |
98 | Address:
99 | {
100 | Street:'Main',
101 | Number:100,
102 | Apartment:{
103 | Floor: 3,
104 | Number:301
105 | }
106 | }
107 | ```
108 |
109 | ## Global Environment and The Global Object
110 |
111 | **Global = not inside a function**
112 |
113 | ## Execution Context
114 |
115 | * Global Object = Window Object in browsers.
116 | * 'this' = Window Object in browsers.
117 | * Link to the Outer Environment
118 | * Your code
119 |
120 | ## Creation Phase:
121 |
122 | * Global Object
123 | * 'this'
124 | * Outer Environment
125 | * "Hoisting" Setup Memory Space for Variables and functions
126 | * Functions are set to memory entirely (name and code).
127 | * Variables are set to a placeholder called _undefined_. Because the JS engine won't know the space until it executes it. All variables are initialy set to _undefined_.
128 |
129 | ```javascript
130 |
131 | b();
132 | console.log(a);
133 |
134 | var a = 'Hello World'
135 |
136 | function b(){
137 | console.log('Called b');
138 | }
139 | // Returns
140 | > 'Called b'
141 | > undefined
142 |
143 | ```
144 |
145 | ## Execution Phase
146 | Executes the code line by line.
147 |
148 | ## Single Threaded Synchronous Execution
149 | One at a time, in order.
150 |
151 | ## Function invocation
152 | Execute, run a function.
153 |
154 | ## Execution Stack
155 |
156 | When a function is called a new execution context is created and put at the top of the execution stack.
157 |
158 | ```javascript
159 |
160 | function b() {}
161 | function a() { b()}
162 | a();
163 | ```
164 |
165 | The execution stack is.
166 |
167 | * b() Execution Context (create and execute)
168 | * a() Execution Context (create and execute)
169 | * Global Execution Context (created and code executed)
170 |
171 | ## Variable environments.
172 | Where the variables live, and how they relate to each other in memory.
173 |
174 | ## Scope Chain
175 | Functions use outer environments to find variables that are not in its execution contexts.
176 | ```javascript
177 |
178 | function b() {
179 | console.log(myVar);
180 | }
181 |
182 | function a() {
183 | var myVar = 2;
184 | b();
185 | }
186 |
187 | var myVar = 1;
188 | a();
189 | //Returns
190 | > 1
191 | //'b' outers environment is the global environment.
192 | ```
193 |
194 | ```javascript
195 |
196 | function a() {
197 |
198 | function b() {
199 | console.log(myVar);
200 | }
201 |
202 | b();
203 | }
204 |
205 | var myVar = 1;
206 | a();
207 |
208 | //Returns
209 | > 2
210 | //'b' outers environment is the 'a' environment.
211 |
212 | ```
213 |
214 | ## Scope
215 | Scope is where a variable is available in your code
216 |
217 | ## ES6 let
218 | Block scoping: define a variable that it is only available in its block(if block, for loop block...), and can not be used until is declared.
219 |
220 | ## Asynchronous
221 | More than one at a time.
222 | Event Queue is processed after the execution stack is empty.
223 |
224 | ```javascript
225 |
226 | // long running function
227 | function waitThreeSeconds() {
228 | var ms = 3000 + new Date().getTime();
229 | while (new Date() < ms){}
230 | console.log('finished function');
231 | }
232 |
233 | function clickHandler() {
234 | console.log('click event!');
235 | }
236 |
237 | // listen for the click event
238 | document.addEventListener('click', clickHandler);
239 |
240 |
241 | waitThreeSeconds();
242 | console.log('finished execution');
243 | //Returns if clicked
244 | > finished function
245 | > finished execution // The execution task is empty
246 | > click event
247 |
248 | ```
249 | # 3 Types and Operators
250 | ## Dynamic Typing
251 | Variable types are figured out while the code is running.
252 |
253 | ## Primitive Types
254 | Data that represent a single value (not an object)
255 |
256 | 1. `undefined`: lack of exixtence (do not set to this value)
257 | 2. `null`: lack of exixtence
258 | 3. `boolean`
259 | 4. `number`: Floating point
260 | 5. `string`
261 | 6. `symbol`: ES6
262 |
263 | ## Operators
264 | A special function written differently as common functions.
265 |
266 | * Infix notation `3 + 4` used in javascript
267 | * Prefix notation `+3 4`
268 | * Postfix notation `3 4+`
269 |
270 | ## Precedence and Associativity
271 | Precedence: Which Operator function gets called first.
272 |
273 | Associativity: What order Operator functions get called: left or right or right to left
274 | ```javascript
275 |
276 | var a = 2, b = 3, c = 4
277 | a = b = c
278 | //all equals to 4
279 | ```
280 | [Operator precedence and Associativity table](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Operator_Precedence)
281 |
282 | ## Coercion
283 | Converting a value to one type to another
284 |
285 | ```javascript
286 |
287 | var a = 1 + '2';
288 | // 12
289 | ```
290 |
291 | ## Comparison Operators
292 | Use `===` 99% of the time unless you want to coarce and you know what you expect of the coarce.
293 |
294 | [Equality comparisons and sameness](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness)
295 |
296 | ## Default values
297 |
298 | ```javascript
299 |
300 | function greet(name){
301 | name = name || ''
302 | console.log('Hello ' + name)
303 | }
304 |
305 | greet();
306 | ```
307 |
308 | # Objects and Functions
309 | ## Objects and Dots
310 |
311 | ```javascript
312 |
313 | var person = new Object();
314 |
315 | person["firstname"] = "Tony";
316 |
317 | var firstNameProperty = "firstname";
318 |
319 | //Computed member access
320 | console.log(person[firstNameProperty]);
321 |
322 | //Member access
323 | console.log(person.firstname);
324 |
325 | // An object inside another object (subobjects).
326 | person.address = new Object();
327 |
328 | // Left to right Associativity. Person then address then street.
329 | person.address.street = "111 Main St.";
330 |
331 | console.log(person.address.street);
332 |
333 | //Same thing
334 | console.log(person["address"]["street"]);
335 |
336 | ```
337 |
338 | ## Object literals
339 |
340 | Shorthand using curly braces.
341 | ```javascript
342 |
343 | var person = {
344 | firstname: 'Tony', // They can be initialized
345 | address: {
346 | street: '111 Main St.',
347 | }
348 | };
349 | ```
350 |
351 | ```javascript
352 |
353 | var Tony = {
354 | firstname: 'Tony',
355 | address: {
356 | street: '111 Main St.',
357 | }
358 | };
359 |
360 | function greet(person) {
361 | console.log('Hi ' + person.firstname);
362 | }
363 |
364 | greet(Tony);
365 |
366 | // Creating an object on the fly
367 | greet({
368 | firstname: 'Mary',
369 | lastname: 'Doe'
370 | });
371 |
372 | // Add new properties on the fly
373 | Tony.address2 = {
374 | street: '333 Second St.'
375 | }
376 | ```
377 |
378 | ## NameSpace
379 |
380 | A container for variables and functions.
381 |
382 | Faking name spacing Containt objects, methods and properties inside a container object.
383 |
384 | ```javascript
385 |
386 | var greet = 'Hello!';
387 | var greet = 'Hola!';
388 |
389 | console.log(greet); // Returns: Hola!
390 |
391 | var english = {};
392 | var spanish = {};
393 |
394 | english.greet = 'Hello!';
395 | spanish.greet = 'Hola!';
396 |
397 | console.log(english); // Returns: Object {greet: "Hello!"}
398 | ```
399 |
400 | ## JSON and Object literals
401 | A JSON is an Object
402 |
403 | An Object could not be a JSON
404 |
405 | Properties have to be wrapped in cuotes
406 |
407 | No functions as values
408 |
409 | **JSON**
410 | ```javascript
411 |
412 | {
413 | "firstname": "Mary",
414 | "isAProgrammer": true
415 | }
416 | ```
417 |
418 | **OBJECT**
419 | ```javascript
420 |
421 | var objectLiteral = {
422 | firstname: 'Mary',
423 | isAProgrammer: true
424 | }
425 |
426 | console.log(JSON.stringify(objectLiteral));
427 |
428 | var jsonValue = JSON.parse('{ "firstname": "Mary", "isAProgrammer": true }');
429 | ```
430 |
431 | ## Functions and Objects
432 |
433 | **First class functions.**
434 | They can:
435 |
436 | * Assign variables to have a value that is a function
437 | * Pass functions as parameters
438 | * Create functions on the fly
439 |
440 | Functions are special Objects.
441 |
442 | They can have
443 |
444 | * Primitives
445 | * Objects
446 | * Other functions
447 |
448 | Only for functions
449 | * **Name**: Can be optional: _annonymous_
450 | * **Code**: is invocable.
451 |
452 | ```javascript
453 |
454 | function greet() {
455 | console.log('hi');
456 | }
457 |
458 | greet.language = 'english';
459 | console.log(greet.language); // 'english'
460 | ```
461 |
462 | ## Function Statements and Expression
463 | **Expression**: unit of code that results in a value
464 |
465 | **Statement**: Does not return a value ie. `if statement`
466 |
467 | Function statement
468 | ```javascript
469 |
470 | //This function has a name, but is not assigned
471 | function greet() {
472 | console.log('hi');
473 | }
474 |
475 | greet();
476 |
477 | ```
478 |
479 | Function expression
480 | ```javascript
481 |
482 | //This function has no name, but is assigned to a variable
483 | var anonymousGreet = function() {
484 | console.log('hi');
485 | }
486 |
487 |
488 | anonymousGreet();
489 |
490 |
491 | ```
492 |
493 | Pass a function to a function
494 |
495 | ```javascript
496 |
497 | function log(a) {
498 | a();
499 | }
500 |
501 | log(function() {
502 | console.log('hi');
503 | });
504 | ```
505 |
506 | ## By Value vs. by Reference
507 |
508 | **Primitive** values are passed **by value**, are copied in a new memory address.
509 |
510 | **Objects** are passed **by reference**, a new pointer is created pointing to the same address.
511 |
512 | `=` Operator sets up a new memory space (new address)
513 |
514 | ```javascript
515 |
516 | var c = { greeting: 'hi' };
517 | var d;
518 | d = c; // d and c point to the same address
519 |
520 | c = { greeting: 'howdy' }; / // d and c do not point anymore to the same address
521 | console.log(c);
522 | console.log(d);
523 |
524 | //Returns
525 | > howdy
526 | > hi
527 | ```
528 |
529 | ## Objects, Functions and 'this'
530 |
531 | Calling `this` from a function, will point always to the `Window` object.
532 |
533 | ```javascript
534 |
535 | function a() {
536 | console.log(this);
537 | }
538 |
539 | var b = function() {
540 | console.log(this);
541 | }
542 |
543 | a();
544 | b();
545 |
546 | //Returns
547 | > Window
548 | > Window
549 | ```
550 |
551 | Object literal with methods. (functions inside an objects are called methods)
552 |
553 | ```javascript
554 |
555 | var c = {
556 | name: 'The c object',
557 | log: function() {
558 | this.name = 'Updated c object';
559 | console.log(this); // Point to the 'c' object
560 | }
561 | }
562 |
563 | c.log(); // Will show the c object where in its 'name' property will be 'Updated c object';
564 | ```
565 |
566 | Creating a function inside an object (an internal function) and using `this` inside it, will point to the `Window` object instead to the object.
567 |
568 | To fix this we can use the `self` pattern.
569 |
570 | ```javascript
571 |
572 | var c = {
573 | name: 'The c object',
574 | log: function() {
575 | var self = this;
576 |
577 | self.name = 'Updated c object';
578 | console.log(self);
579 |
580 | var setname = function(newname) {
581 | this.name = newname; // Here 'this' points to the 'Window' object instead of to 'c'
582 | self.name = newname; // Here 'this' points to 'c'
583 | }
584 | setname('Updated again! The c object');
585 | console.log(self);
586 | }
587 | }
588 |
589 | c.log();
590 | ```
591 | ## Arrays
592 | Arrays can hold anything and we can use them without any problem.
593 |
594 | ```javascript
595 |
596 | var arr = [
597 | 1,
598 | false,
599 | {
600 | name: 'Tony',
601 | address: '111 Main St.'
602 | },
603 | function(name) {
604 | var greeting = 'Hello ';
605 | console.log(greeting + name);
606 | },
607 | "hello"
608 | ];
609 |
610 | console.log(arr);
611 | arr[3](arr[2].name); // 'Hello Tony'
612 |
613 | ```
614 |
615 | ## 'arguments' and SPREAD
616 |
617 | The keyword `arguments` hold all the parameters that you pass to a function.
618 | `arguments` is an _array like_ value.
619 |
620 | ```javascript
621 |
622 | function greet(firstname, lastname, language) {
623 | if (arguments.length === 0) {
624 | console.log('Missing parameters!');
625 | return;
626 | }
627 | console.log(arguments);
628 | console.log('arg 0: ' + arguments[0]);
629 | }
630 |
631 | greet(); // Does not break
632 | greet('John'); // Sets 'John' to the first parameter
633 |
634 | // in ES6 I can do: function greet(firstname, ...other)
635 | // and 'other' will be an array that contains the rest of the arguments
636 | ```
637 |
638 | ## Overloading
639 |
640 | Just create a function with different names.
641 |
642 | ```javascript
643 |
644 | function greet(firstname, lastname, language) {
645 | ...
646 | }
647 |
648 | function greetEnglish(firstname, lastname) {
649 | greet(firstname, lastname, 'en');
650 | }
651 |
652 | greetEnglish('John', 'Doe');
653 | ```
654 |
655 | ## Automatic semicolon insertion
656 | Always put semicolons to avoid automatic insertion problems.
657 |
658 | Because there is a new line after `return` javascript automatically inserts a semicolon. Use `return {` instead
659 | ```javascript
660 |
661 | // unreachable code after return statement
662 | function getPerson() {
663 | return
664 | {
665 | firstname: 'Tony'
666 | }
667 | }
668 |
669 | console.log(getPerson());
670 |
671 | ```
672 |
673 | ## Immediately Invoked Functions Expressions (IIFEs)
674 | Run the function at the point it is created. Add a `()` after its declaration.
675 |
676 | ```javascript
677 |
678 | // function statement. Have to have a name.
679 | function greet(name) {
680 | console.log('Hello ' + name);
681 | }
682 | greet('John');
683 |
684 | // using a function expression
685 | var greetFunc = function(name) {
686 | console.log('Hello ' + name);
687 | };
688 | greetFunc('John');
689 |
690 | // using an Immediately Invoked Function Expression (IIFE)
691 | var greeting = function(name) {
692 | console.log('Hello ' + name);
693 | }('John');
694 | ```
695 |
696 | **IIFE**
697 | ```javascript
698 |
699 | var firstname = 'John';
700 |
701 | //Function statement wrapped in parenthesis so javascript treat is as valid
702 | // Remember function statement have to have a name.
703 | (function(name) {
704 |
705 | var greeting = 'Inside IIFE: Hello';
706 | console.log(greeting + ' ' + name);
707 |
708 | }(firstname)); // IIFE Execute the function on the fly
709 | ```
710 |
711 | ## IIFE and Safe code
712 | Frameworks normally use IIFE to have its code close to external code.
713 | An IIFE runs in its own execution context.
714 | A framework would start with a parenthesis and close with another.
715 |
716 | ```javascript
717 |
718 | (function(global, name) {
719 | var greeting = 'Hello';
720 | global.greeting = 'Hello'; //We can access the global object passing it as a parameter.
721 | console.log(greeting + ' ' + name);
722 |
723 | }(window, 'John')); // IIFE
724 | ```
725 |
726 | ## Closures
727 |
728 | Closures allow us to access variables whose execution context has been remove from execution stack.
729 | `greet` context is removed after `var sayHi = greet('Hi');`is executed, but `sayHi('Tony');` still have access to the variable `whattosay` that is needed to execute the annonymous function inside `greet` This is because javascript allows executon contexts to closes in its outer variables.
730 |
731 | ```javascript
732 |
733 | function greet(whattosay) {
734 |
735 | return function(name) {
736 | console.log(whattosay + ' ' + name);
737 | }
738 | }
739 |
740 | var sayHi = greet('Hi');
741 | sayHi('Tony');
742 | ```
743 |
744 |
745 | ```javascript
746 |
747 | function buildFunctions() {
748 | var arr = [];
749 | for (var i = 0; i < 3; i++) {
750 | let j = i;
751 | arr.push(
752 | function() {
753 | console.log(i);// Returns always 3, because the last state of the i val in memory is 3
754 | console.log(j);// Returns 0,1,2, beacuase 'let' is scope to the block, and makes a new variable every time in a different scope.
755 | }
756 | )
757 | }
758 |
759 | return arr;
760 | }
761 |
762 | var fs = buildFunctions();
763 |
764 | fs[0]();
765 | fs[1]();
766 | fs[2]();
767 | ```
768 |
769 | To make it work in prior ES6 We need to have `i` in a new execution context everytime the loop runs. Use IIFE
770 |
771 | ```javascript
772 |
773 | function buildFunctions2() {
774 |
775 | var arr = [];
776 |
777 | for (var i = 0; i < 3; i++) {
778 | arr.push(
779 | (function(j) { // This function will be executed in a differnt execution context,
780 | // and all of them will be closed in in its closure.
781 | return function() { // We push the return of this function. So when this is call, instead of going up until the loop context, it only goes until the IIFE where 'j' was stored.
782 | console.log(j);
783 | }
784 | }(i))
785 | )
786 | }
787 | return arr;
788 | }
789 | ```
790 |
791 | ## Function Factories
792 |
793 | ```javascript
794 |
795 | function makeGreeting(language) {
796 |
797 | return function(firstname, lastname) {
798 |
799 | if (language === 'en') {
800 | console.log('Hello ' + firstname + ' ' + lastname);
801 | }
802 |
803 | if (language === 'es') {
804 | console.log('Hola ' + firstname + ' ' + lastname);
805 | }
806 | }
807 | }
808 |
809 | var greetEnglish = makeGreeting('en'); // They were created in differnt execution contexts.
810 | var greetSpanish = makeGreeting('es');
811 | ```
812 |
813 | ## Callback function
814 | A function you give to another function when the other function is finished.
815 |
816 | ## Function
817 | Is a special type of object
818 |
819 | It has:
820 |
821 | * Name: optional
822 | * Code: invocable using '()'
823 | * bind() set 'this' to what we pass as parameter
824 | * call() like bind but it also execute and can get parameters
825 | * apply() same as call, but parameters have to be an array
826 |
827 | ```javascript
828 |
829 | var person = {
830 | firstname: 'John',
831 | lastname: 'Doe',
832 | getFullName: function() {
833 |
834 | var fullname = this.firstname + ' ' + this.lastname;
835 | return fullname;
836 |
837 | }
838 | }
839 |
840 | var logName = function(lang1, lang2) {
841 | console.log('Logged: ' + this.getFullName());
842 | }
843 |
844 | var logPersonName = logName.bind(person);
845 | logPersonName('en');
846 |
847 | logName.call(person, 'en', 'es');
848 | logName.apply(person, ['en', 'es']);
849 |
850 | ```
851 |
852 | ## Function borrowing
853 | ```javascript
854 |
855 | var person2 = {
856 | firstname: 'Jane',
857 | lastname: 'Doe'
858 | }
859 |
860 | console.log(person.getFullName.apply(person2));//or call()
861 | ```
862 |
863 | ## Function currying
864 | A copy of a function with preset parameters.
865 |
866 | ```javascript
867 |
868 | function multiply(a, b) {
869 | return a*b;
870 | }
871 |
872 | var multipleByTwo = multiply.bind(this, 2);
873 | console.log(multipleByTwo(4)); // 8
874 |
875 | var multipleByThree = multiply.bind(this, 3);
876 | console.log(multipleByThree(4)); //12
877 |
878 | ```
879 |
880 | ## Functional programming
881 | ```javascript
882 |
883 | function mapForEach(arr, fn) {
884 |
885 | var newArr = [];
886 | for (var i=0; i < arr.length; i++) {
887 | newArr.push(
888 | fn(arr[i])
889 | )
890 | };
891 |
892 | return newArr;
893 | }
894 |
895 | var arr1 = [1,2,3];
896 | console.log(arr1);
897 |
898 | // Sample 1 add a function
899 | var arr2 = mapForEach(arr1, function(item) {
900 | return item * 2;
901 | });
902 | console.log(arr2); // [2,4,6];
903 |
904 | // Sample 2 differnt output type
905 | var arr3 = mapForEach(arr1, function(item) {
906 | return item > 2;
907 | });
908 | console.log(arr3); //[false,false,true]
909 |
910 | // Sample 3 Add function with new parameters
911 | var checkPastLimit = function(limiter, item) {
912 | return item > limiter;
913 | }
914 | var arr4 = mapForEach(arr1, checkPastLimit.bind(this, 1)); // bind is needed so we have a function that use only one parameter.
915 | console.log(arr4); //[false,true,true]
916 |
917 | // Sample 4 Simplify function with new parameters
918 | //We can also simplified this not to use bind all the time
919 | var checkPastLimitSimplified = function(limiter) {
920 | return function(limiter, item) {
921 | return item > limiter;
922 | }.bind(this, limiter);
923 | };
924 |
925 | var arr5 = mapForEach(arr1, checkPastLimitSimplified(1));
926 | console.log(arr5);
927 |
928 | ```
929 |
930 | Try to use always unmutable objects and return always new objects
931 |
932 | ## Udnerscore.js
933 |
934 | [Underscore](http://underscorejs.org/docs/underscore.html)
935 | [lodash](https://lodash.com/)
936 |
937 | ```javascript
938 |
939 | var arr6 = _.map(arr1, function(item) { return item * 3 });
940 | console.log(arr6);
941 |
942 | var arr7 = _.filter([2,3,4,5,6,7], function(item) { return item % 2 === 0; });
943 | console.log(arr7);
944 |
945 | ```
946 |
947 | # Object Oriented JavaScript Prototypal Inheritance
948 | ## Inheritance
949 | One object gets access to the properties and methods of another object.
950 |
951 | ## Classical Inheritance
952 | Java, C++, ...
953 |
954 | ## Prototypal Inheritance
955 | JavaScript
956 | Simple, flexible, extensible.
957 |
958 | **Prototype** an object that is used (Inherited) by another object.
959 | Prototype chain. The chain of Prototypes that an object has.
960 |
961 | ```javascript
962 |
963 | var person = {
964 | firstname: 'Default',
965 | lastname: 'Default',
966 | getFullName: function() {
967 | return this.firstname + ' ' + this.lastname;
968 | }
969 | }
970 |
971 | var john = {
972 | firstname: 'John',
973 | lastname: 'Doe'
974 | }
975 |
976 | // don't do this EVER! for demo purposes only!!!
977 | john.__proto__ = person;
978 | console.log(john.getFullName()); // John Doe. 'this' will be set in the prototype from the object origianted the call. In this case John.
979 | console.log(john.firstname); // John
980 |
981 | var jane = {
982 | firstname: 'Jane'
983 | }
984 |
985 | jane.__proto__ = person;
986 | console.log(jane.getFullName()); // Jane Default
987 | ```
988 |
989 | ## Reflection
990 | An object can look at itself, listening and changing its properties and methods
991 |
992 | ```javascript
993 |
994 | // don't do this EVER! for demo purposes only!!!
995 | john.__proto__ = person;
996 |
997 | for (var prop in john) {
998 | console.log(prop + ': ' + john[prop]); // prop = firstname, lastname and getFullName
999 | if (john.hasOwnProperty(prop)) { // if is the object not in the prototype
1000 | console.log(prop + ': ' + john[prop]); // prop = firstname and lastname
1001 | }
1002 | }
1003 | ```
1004 |
1005 | **Extend** (Assign)
1006 | Underscore library that place the properties in the object passed.
1007 |
1008 | ```javascript
1009 |
1010 | var jane = {
1011 | address: '111 Main St.',
1012 | getFormalFullName: function() {
1013 | return this.lastname + ', ' + this.firstname;
1014 | }
1015 | }
1016 |
1017 | var jim = {
1018 | getFirstName: function() {
1019 | return firstname;
1020 | }
1021 | }
1022 |
1023 | _.extend(john, jane, jim); //John will have the same properties as jim and jane
1024 |
1025 | console.log(john);
1026 |
1027 | //Returns
1028 | address: "111 Main St."
1029 | firstname: "John"
1030 | getFirstName: ()
1031 | getFormalFullName: ()
1032 | lastname: "Doe"
1033 | ```
1034 |
1035 | # Building Objects
1036 | ## _new_
1037 |
1038 | `new` set the this keyword to a new empty object
1039 | If nothing is return from that function, instead of returning _undefined_ it will return an empty object.
1040 |
1041 | **Function constructor**. A function that lets me construct an object
1042 |
1043 | ```javascript
1044 |
1045 | function Person(firstname, lastname) { // This is a function constructor.
1046 |
1047 | console.log(this); // Returns an empty object
1048 | this.firstname = firstname;
1049 | this.lastname = lastname;
1050 | console.log('This function is invoked.'); // It is invoked because we called `new`
1051 |
1052 | }
1053 |
1054 | var john = new Person('John', 'Doe');
1055 | console.log(john); // Person { firstname: "John", lastname: "Doe" }
1056 | ```
1057 |
1058 | ## Function constructors and Prototypes
1059 | All functions have a prototype. An empty Object. Use only by the `new` operator.
1060 |
1061 | ```javascript
1062 |
1063 | Person.prototype.getFullName = function() {
1064 | returning this.firstname + ' ' + this.lastname;
1065 | }
1066 |
1067 | var john = new Person('John', 'Doe'); // john points to Person.prototype as its prototype.
1068 | console.log(john);
1069 | //Returns
1070 | firstname: "John"
1071 | lastname: "Doe"
1072 | __proto__: Person
1073 | constructor: Person(firstname, lastname)
1074 | getFullName: ()
1075 | ```
1076 |
1077 | Why not having functions in the function constructor?
1078 | Every copy of the object will get a copy of the function (space in memory). If we have it in the prototype, only one copy of the function will exist in memory for any number of objects created.
1079 |
1080 | Use Capital letters as first letter in any function constructor to identify it easily as a function constructor and reduce possible errors when calling them. Use Linters to help you with the process.
1081 |
1082 | ## Built in Function Constructor
1083 | Create objects that have primitives
1084 | ```javascript
1085 |
1086 | var a = new Number(3) // a --> Number {[[PrimitiveValue]]: 3}
1087 |
1088 | var b = new String("Hugo") // b --> String {0: "H", 1: "u", 2: "g", 3: "o", length: 4, [[PrimitiveValue]]: "Hugo"}
1089 | // inside of the String object there is a primitive.
1090 |
1091 | ```
1092 | Good to add functions to primitives objects
1093 |
1094 | ```javascript
1095 |
1096 | String.prototype.isLengthGreaterThan = function(limit) {
1097 | return this.length > limit;
1098 | }
1099 |
1100 | console.log("John".isLengthGreaterThan(3)); // true
1101 |
1102 | Number.prototype.isPositive = function() {
1103 | return this > 0;
1104 | }
1105 | console.log(3.isPositive); // ERROR: 3 is not an object.
1106 |
1107 | var a = new Number(3)
1108 | a.isPositive() // true
1109 | ```
1110 |
1111 | **They are dangeorous** better do not use built in function constructor, unless you really need them.
1112 | You can look for libraries that help you. Like momentjs for Dates, instead of building your owns function constructor.
1113 |
1114 | ## Arrays and for..in
1115 | In an array the property name are the indexes, that is why we can use it in square brackets. `myArray[0]`
1116 |
1117 | ```javascript
1118 |
1119 | var arr = ['John', 'Jane', 'Jim']
1120 | for (var prop in arr) {
1121 | console.log(prop + ': ' + arr[prop]); // 0:John, 1:Jane, 2:Jim
1122 | }
1123 | // If we add
1124 | Array.prototype.myFeature='cool'; // it will return 0:John, 1:Jane, 2:Jim, myFeature:'cool'
1125 | //Use normal for loop
1126 |
1127 | ```
1128 | ## _Object.create_ and Pure prototypal inheritance
1129 |
1130 | ```javascript
1131 |
1132 | var person = {
1133 | firstname: 'Default',
1134 | lastname: 'Default',
1135 | greet: function() {
1136 | return 'Hi ' + this.firstname;
1137 | }
1138 | }
1139 |
1140 | var john = Object.create(person); // Creates an empty object with the prototype of person
1141 | john.firstname = 'John'; // Adds value
1142 | john.lastname = 'Doe';
1143 | console.log(john);
1144 | ```
1145 |
1146 | We can add functions on the fly.
1147 |
1148 | ## Polyfill
1149 | Code that adds a feature which the engine _may_ lack
1150 |
1151 | ```javascript
1152 |
1153 | // Object.create POLYFILL
1154 | if (!Object.create) {
1155 | Object.create = function (o) {
1156 | if (arguments.length > 1) {
1157 | throw new Error('Object.create implementation'
1158 | + ' only accepts the first parameter.');
1159 | }
1160 | function F() {} // Creates an empty function
1161 | F.prototype = o; // Set the prototype of the function equal to the object we passed
1162 | return new F(); // Creates a new empty obecjt, runs an empty function and points the prototype of the new empty object to what we passed in.
1163 | };
1164 | }
1165 | ```
1166 | The object becomes a
1167 |
1168 | ## ES6 and Classes
1169 |
1170 | _class_ at the end it is just an object and _extends_ is syntactic sugar.
1171 |
1172 | ## _typeof_ and _instanceof_
1173 | ```javascript
1174 |
1175 | console.log(typeof 3); //number
1176 |
1177 | console.log(typeof "Hello"); // String
1178 |
1179 | console.log(typeof {}); //Object
1180 |
1181 | var d = [];
1182 | console.log(typeof d); // Object.
1183 | console.log(Object.prototype.toString.call(d)); // better! [object Array]
1184 | ```
1185 |
1186 | ```javascript
1187 |
1188 | function Person(name) {
1189 | this.name = name;
1190 | }
1191 |
1192 | var e = new Person('Jane');
1193 | console.log(typeof e); // object
1194 | console.log(e instanceof Person); // true
1195 |
1196 | console.log(typeof undefined); // undefined
1197 | console.log(typeof null); // Object. a bug since, like, forever...
1198 |
1199 | var z = function() { };
1200 | console.log(typeof z); // function
1201 | ```
1202 |
1203 | ## Strict Mode
1204 |
1205 | ```javascript
1206 |
1207 | function logNewPerson() {
1208 | "use strict";
1209 |
1210 | var person2;
1211 | persom2 = {};
1212 | console.log(persom2); //Uncaught exception
1213 | }
1214 |
1215 | var person;
1216 | persom = {};
1217 | console.log(persom);
1218 | logNewPerson();
1219 | ```
1220 | ## Method Chaining
1221 | Calling one method after another, and each method affects the parent object.
1222 |
1223 | # Own Libraries architect as jQuery
1224 | ## Greetr
1225 | ```javascript
1226 |
1227 | // IEFF needs the global object and the jQuery reference
1228 | ;(function(global, $) {
1229 |
1230 | var Greetr = function(firstName, lastName, language){
1231 | // Create a new Function Constructor which has the same parameters as the called
1232 | // one from the client, but we return a new Object. The new object is created
1233 | // because we call 'new' to a Function Constructor
1234 | return new Greetr.init(firstName, lastName, language);
1235 | }
1236 |
1237 | // No access is possible here from outside the lobrarys
1238 | var supportedLangs = ['en', 'es'];
1239 |
1240 | // Declaring and creating new variables that are not expose outside
1241 | var greetings = {
1242 | en:'Hello',
1243 | es:'Hola'
1244 | };
1245 |
1246 | var formalGreetings = {
1247 | en:'Greetings',
1248 | es:'Saludos'
1249 | };
1250 |
1251 | var logMessages = {
1252 | en:'Logged in',
1253 | es:'Sesion iniciada'
1254 | };
1255 |
1256 | Greetr.prototype = {
1257 | // Exposed functions
1258 | fullName: function() {
1259 | return this.firstName +' '+ this.lastName;
1260 | },
1261 |
1262 | validate: function(){
1263 | if( supportedLangs.indexOf(this.language)==-1 ){
1264 | throw "Invalid language"
1265 | }
1266 | },
1267 |
1268 | greeting: function(){
1269 | return greetings[this.language] + ' ' + this.firstName + '!';
1270 | },
1271 |
1272 | formalGreeting: function(){
1273 | return formalGreetings[this.language] + ', ' + this.fullName();
1274 | },
1275 |
1276 | greet: function(formal) {
1277 | var msg;
1278 |
1279 | // if undefined or null it will be coerced to 'false'
1280 | if (formal) {
1281 | msg = this.formalGreeting();
1282 | }
1283 | else {
1284 | msg = this.greeting();
1285 | }
1286 |
1287 | if (console) {
1288 | console.log(msg);
1289 | }
1290 |
1291 | // 'this' refers to the calling object at execution time
1292 | // makes the method chainable
1293 | return this;
1294 | },
1295 |
1296 | log: function() {
1297 | if (console) {
1298 | console.log(logMessages[this.language] + ': ' + this.fullName());
1299 | }
1300 | return this;
1301 | },
1302 |
1303 | setLang: function(lang) {
1304 | this.language = lang;
1305 | this.validate();
1306 | return this;
1307 | },
1308 |
1309 | HTMLgreeting: function(selector, formal){
1310 | if(!$){
1311 | throw 'jQuery not loaded';
1312 | }
1313 | if(!selector){
1314 | throw 'Missing jQuery selector'
1315 | }
1316 |
1317 | var msg;
1318 | if (formal) {
1319 | msg = this.formalGreeting();
1320 | }
1321 | else {
1322 | msg = this.greeting();
1323 | }
1324 | $(selector).html(msg);
1325 | return this;
1326 | }
1327 |
1328 | };
1329 |
1330 | Greetr.init = function(firstName, lastName, language){
1331 | // Keep 'this' safe to the future calls. We will always have this object in 'self'
1332 | var self = this;
1333 | // Default values
1334 | self.firstName = firstName || '';
1335 | self.lastName = lastName || '';
1336 | self.language = language || "en"
1337 |
1338 | self.validate()
1339 | }
1340 |
1341 | // 'Greetr.init.prototype' is the prototype of the init function. Every function
1342 | // '.prototype' is where the prototype is. We wnat that our object prototype is
1343 | // 'Greetr.prototype' that we will define ourself.
1344 | // That way we point 'Greetr.init.prototype' to 'Greetr.prototype'.
1345 | Greetr.init.prototype = Greetr.prototype;
1346 |
1347 | //Attach it to the global object to be accessed everywhere and Alias to G$
1348 | global.Greetr = global.G$ = Greetr;
1349 |
1350 |
1351 | }(window, jQuery)); // we call teh function with the window(global) object and the jQuery reference
1352 | ```
1353 | # Bonus
1354 | ## Transpile
1355 | Convert the syntax of one programming language, to another.
1356 |
--------------------------------------------------------------------------------
/gitignore:
--------------------------------------------------------------------------------
1 | Code/
--------------------------------------------------------------------------------
/greetr.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HugoMatilla/JavaScriptCheatSheet/503e44536c5ea5b31de8ec04c8d60bc3c51df7f4/greetr.js
--------------------------------------------------------------------------------