├── .gitignore
├── _config.yml
├── index.html
├── func-prog
└── index.js
├── promises
└── index.js
├── README.md
├── bind-in-es5class
└── index.js
├── generators
└── index.js
├── object-literals
└── index.js
├── template-literals
└── index.js
├── closures
└── index.js
├── default-params
└── index.js
├── func-curry
└── index.js
├── arrow-func
└── index.js
├── async-await
└── index.js
├── spread
└── index.js
├── destruct
└── index.js
├── let-const-var
└── index.js
├── proxies
└── index.js
├── bind-call-apply
└── index.js
├── app.js
└── array-func
└── index.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-minimal
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | JS Master
8 |
9 |
10 | Open Browser Page Inspector
11 | Clicking each of the links will execute the js examples in repository
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/func-prog/index.js:
--------------------------------------------------------------------------------
1 | (function(context) {
2 | function multiplesOf2(x) {
3 | return x % 2 === 0;
4 | }
5 |
6 | function traverse(arr, func) {
7 | const result = [];
8 | for (let i = 0; i < arr.length; i++)
9 | result.push(func(arr[i]));
10 | return result;
11 | }
12 |
13 | function demo() {
14 | console.log('\n\nFUNCTIONAL PROGRAMMING');
15 | const arr = [1,2,3,4,5,6,7,8];
16 | let result = traverse(arr, multiplesOf2);
17 | console.log(result);
18 | result = traverse(arr, function (x) {
19 | return x * x;
20 | });
21 | console.log(result);
22 | result = traverse(arr, (x) => 10 * x );
23 | console.log(result);
24 | };
25 |
26 | (context || this).demoLibs['func-prog'] = demo;
27 | })(window);
28 |
--------------------------------------------------------------------------------
/promises/index.js:
--------------------------------------------------------------------------------
1 | (function(context) {
2 |
3 | function demo() {
4 | console.log('\n\nPROMISES');
5 |
6 | // a promise generator function, returning new promise
7 | // which executes a setTimeout resolving after 1 sec
8 | const timeoutPromise = () => new Promise((resolve, reject) => { setTimeout(resolve, 1000) });
9 |
10 | // simple promise and then
11 | timeoutPromise()
12 | .then(() => console.log('Yo!'));
13 |
14 | // promise chaining
15 | timeoutPromise()
16 | .then(() => timeoutPromise())
17 | .then(() => console.log('YoYo!'));
18 |
19 | timeoutPromise()
20 | .then(() => timeoutPromise())
21 | .then(() => timeoutPromise())
22 | .then(() => console.log('YoYoYo!'));
23 | };
24 |
25 | (context || this).demoLibs['promises'] = demo;
26 | })(window);
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Art of JS
2 |
3 | > Learn the art of Javascript, with simple, to the point examples
4 |
5 | ### Topics:
6 | 1. [Array functions](array-func/index.js)
7 | 2. [Arrow functions](arrow-func/index.js)
8 | 3. [Async Await](async-await/index.js)
9 | 4. [Bind Call Apply](bind-call-apply/index.js)
10 | 5. [Closures](closures/index.js)
11 | 6. [Default parameters](default-params/index.js)
12 | 7. [Desctructuring](destruct/index.js)
13 | 8. [Function currying](func-curry/index.js)
14 | 9. [Functional programming](func-prog/index.js)
15 | 10. [Generators](generators/index.js)
16 | 11. [Let Const Var](let-const-var/index.js)
17 | 12. [Object literals](object-literals/index.js)
18 | 13. [Promises](promises/index.js)
19 | 14. [Proxies/ Revocable Proxies](proxies/index.js)
20 | 15. [Spread](spread/index.js)
21 | 16. [Template / Tagged Template literals](template-literals/index.js)
22 |
--------------------------------------------------------------------------------
/bind-in-es5class/index.js:
--------------------------------------------------------------------------------
1 | (function (context) {
2 |
3 | function Driver(name) {
4 | this.name = name;
5 | }
6 |
7 | Driver.prototype.displayScore = function (score) {
8 | console.log("Score for " + this.name + ": " + score);
9 | };
10 |
11 |
12 | Driver.prototype.getScore = function () {
13 | setTimeout(function () {
14 | this.displayScore(10);
15 | }.bind(this), 1000);
16 |
17 | // another approach here without using this is:
18 | // var that = this;
19 | // setTimeout(function () {
20 | // that.displayScore(10);
21 | // }, 1000);
22 |
23 | // another approach using arrow operator
24 | //setTimeout(() => this.displayScore(10), 1000);
25 |
26 | };
27 |
28 | function demo() {
29 | new Driver("Test driver").getScore();
30 | }
31 |
32 | (context || this).demoLibs['bind'] = demo;
33 | })(window);
34 |
--------------------------------------------------------------------------------
/generators/index.js:
--------------------------------------------------------------------------------
1 | (function(context) {
2 |
3 | function *foo(x) {
4 | yield 1;
5 | yield 2;
6 | yield x;
7 | }
8 |
9 | function *bar(x) {
10 | const y = 10 * (yield (x + 2));
11 | const z = yield (y / 5);
12 | return (x + y + z);
13 | }
14 |
15 | function demo() {
16 | console.log('\n\nGENERATORS');
17 |
18 | const iter = foo(3);
19 | console.log(iter.next()); // { value:1, done:false }
20 | console.log(iter.next()); // { value:2, done:false }
21 | console.log(iter.next()); // { value:3, done:false }
22 | console.log(iter.next()); // { value:undefined, done:true }
23 |
24 | for (const v of foo(10)) {
25 | console.log(v);
26 | }
27 |
28 | const iterBar = bar(100);
29 | console.log(iterBar.next()); // { value:102, done:false }
30 | console.log(iterBar.next(5)); // { value:10, done:false }
31 | console.log(iterBar.next(30)); // { value:180, done:true }
32 | };
33 |
34 | (context || this).demoLibs['generators'] = demo;
35 | })(window);
36 |
--------------------------------------------------------------------------------
/object-literals/index.js:
--------------------------------------------------------------------------------
1 | (function(context) {
2 |
3 | function demo() {
4 | console.log('\n\nOBJECT LITERALS');
5 |
6 | const employee = {
7 | id: '1234',
8 | name: {
9 | title: 'Dr.',
10 | firstName: 'Strange',
11 | lastName: ''
12 | },
13 | address: {
14 | street: '890',
15 | locality: 'Fifth Avenue',
16 | city: 'Manhattan',
17 | state: 'New York',
18 | }
19 | };
20 |
21 | // Use of object destructuring
22 | const { title, firstName, lastName } = employee.name;
23 | const name = `${title} ${firstName} ${lastName}`;
24 |
25 | const { street, locality, city, state } = employee.address;
26 | const address = `${street} ${locality} ${city} ${state}`;
27 |
28 | // Use of object literals
29 | const employeeShort = {
30 | name,
31 | address,
32 | id: employee.id,
33 | };
34 |
35 | console.log(employee);
36 | console.log(employeeShort);
37 | }
38 |
39 | (context || this).demoLibs['object-literals'] = demo;
40 | })(window);
41 |
--------------------------------------------------------------------------------
/template-literals/index.js:
--------------------------------------------------------------------------------
1 | (function(context) {
2 |
3 | // tagged literal function receives two parameters
4 | // tokens - string tokens, around the placeholders
5 | // values - list of values to replace in string literal placeholders
6 | function capitalize(tokens = [], ...values) {
7 | return tokens.reduce((acc, x, i) => {
8 | return acc + x + `${values[i] || ''}`.toUpperCase();
9 | }, '');
10 | }
11 |
12 | function demo() {
13 | console.log('\n\nTEMPLATE LITERALS');
14 | const person = {
15 | firstName: 'John',
16 | lastName: 'Doe',
17 | age: 27
18 | }
19 |
20 | const { firstName, lastName, age } = person;
21 |
22 | const output = `
23 | First Name: ${firstName}\n
24 | Last Name: ${lastName}\n
25 | Age: ${age}
26 | `;
27 | console.log(output);
28 |
29 | const outputTaggedTemplate = capitalize`
30 | First Name: ${firstName}\n
31 | Last Name: ${lastName}\n
32 | Age: ${age}
33 | `;
34 | console.log(outputTaggedTemplate);
35 | };
36 |
37 | (context || this).demoLibs['template-literals'] = demo;
38 | })(window);
39 |
--------------------------------------------------------------------------------
/closures/index.js:
--------------------------------------------------------------------------------
1 | (function(context) {
2 |
3 | // longRunningTask is a simple function taking url,
4 | // & callbacks for success and failure
5 | function longRunningTask(url, success, failure) {
6 | if(url) {
7 | return success('{\"name\":\"John Doe\",\"age\":27}');
8 | } else {
9 | return failure(404, 'no resource found');
10 | }
11 | }
12 |
13 | // successCallback returns another function which can be called later,
14 | // whilst still having access to data param in successCallback
15 | function successCallback(data) {
16 | return function() {
17 | const minimumAge = 21;
18 | data = JSON.parse(data);
19 | if (data.age < minimumAge) {
20 | return `Deny User - Age less than ${minimumAge}`;
21 | }
22 | return 'Allow User';
23 | }
24 | }
25 |
26 | function failureCallback(error, reason) {
27 | return function() {
28 | console.log(`${error} - ${reason}`);
29 | }
30 | }
31 |
32 | function demo() {
33 | console.log('\n\nCLOSURES');
34 | // returns function from successCallback
35 | const returnVal = longRunningTask('sample-url', successCallback, failureCallback);
36 | // prints the data
37 | console.log(returnVal());
38 | };
39 |
40 | (context || this).demoLibs['closures'] = demo;
41 | })(window);
42 |
--------------------------------------------------------------------------------
/default-params/index.js:
--------------------------------------------------------------------------------
1 | (function(context) {
2 |
3 | function greetWithoutDefaultParams(name, language) {
4 | switch(language || 'en') {
5 | case 'en': console.log(`Hello ${name}`); break;
6 | case 'es': console.log(`Hola ${name}`); break;
7 | }
8 | }
9 |
10 | function greetWithoutDefaultParamsCheckWithArguments(name, language) {
11 | // example of strict check
12 | if (arguments.length < 2) return;
13 | switch(language) {
14 | case 'en': console.log(`Hello ${name}`); break;
15 | case 'es': console.log(`Hola ${name}`); break;
16 | }
17 | }
18 |
19 | // function accepts param language with default value 'en'
20 | function greetWithDefaultParams(name, language = 'en') {
21 | switch(language) {
22 | case 'en': console.log(`Hello ${name}`); break;
23 | case 'es': console.log(`Hola ${name}`); break;
24 | }
25 | }
26 |
27 | function demo() {
28 | console.log('\n\nDEFAULT PARAMS');
29 |
30 | greetWithDefaultParams('John Doe');
31 | greetWithDefaultParams('John Doe', 'es');
32 |
33 | greetWithoutDefaultParams('James Bond');
34 | greetWithoutDefaultParams('James Bond', 'es');
35 |
36 | greetWithoutDefaultParamsCheckWithArguments('John Wick');
37 | greetWithoutDefaultParamsCheckWithArguments('John Wick', 'es');
38 | };
39 |
40 | (context || this).demoLibs['default-params'] = demo;
41 | })(window);
42 |
--------------------------------------------------------------------------------
/func-curry/index.js:
--------------------------------------------------------------------------------
1 | (function(context) {
2 |
3 | function multiply(a, b) {
4 | return a * b;
5 | }
6 |
7 | function greet(language, person) {
8 | const greet = language === 'es' ? 'Hola' : 'Hello';
9 | console.log(`${greet} ${person.fname} ${person.lname}`);
10 | }
11 |
12 | function goodbye(language) {
13 | return function(person) {
14 | const goodbye = language === 'ru' ? 'Dasvidaniya' : 'Good bye';
15 | console.log(`${goodbye} ${person.fname} ${person.lname}`);
16 | }
17 | }
18 |
19 | function demo() {
20 |
21 | const johnSnow = {
22 | fname: 'John',
23 | lname: 'Snow'
24 | };
25 |
26 | // curried function call
27 | goodbye('ru')(johnSnow);
28 | // or
29 | const goodbyeInEnglish = goodbye('en');
30 | const goodbyeInRussian = goodbye('ru');
31 |
32 | goodbyeInEnglish(johnSnow);
33 | goodbyeInRussian(johnSnow);
34 |
35 | // regular function call
36 | greet('es', johnSnow);
37 |
38 | // curried using bind
39 | const greetInEnglish = greet.bind(this, 'en');
40 | const greetInSpanish = greet.bind(this, 'es');
41 |
42 | greetInEnglish(johnSnow);
43 | greetInSpanish(johnSnow);
44 |
45 | // also few other functions curried with bind
46 | const twice = multiply.bind(this, 2);
47 | const thrice = multiply.bind(this, 3);
48 |
49 | console.log(twice(5));
50 | console.log(thrice(10));
51 | }
52 |
53 | (context || this).demoLibs['func-curry'] = demo;
54 | })(window);
55 |
--------------------------------------------------------------------------------
/arrow-func/index.js:
--------------------------------------------------------------------------------
1 | (function(context) {
2 |
3 | function printUpperCase() {
4 | const self = this;
5 | console.log(self);
6 | self.string = self.string.toUpperCase();
7 | return function() {
8 | console.log(this); // window this
9 | console.log(this.string);
10 | console.log(self.string);
11 | }
12 | }
13 |
14 | function printUpperCaseFatArrow() {
15 | console.log(this);
16 | this.string = this.string.toUpperCase();
17 | return () => console.log(this.string);
18 | }
19 |
20 | function demo() {
21 | console.log('\n\nARROW FUNCTIONS');
22 |
23 | printUpperCase.call({ string: 'Hello John Doe' })();
24 | printUpperCaseFatArrow.call({ string: 'Hello John Doe' })();
25 |
26 | const person = {
27 | firstName: 'John',
28 | lastName: 'Doe',
29 | printNameFatArrow: () => `${this.firstName} ${this.lastName}`,
30 | printNameRegular: function() { return `${this.firstName} ${this.lastName}` },
31 | printName() { return `${this.firstName} ${this.lastName}` },
32 | }
33 |
34 | console.log(person.printNameFatArrow());
35 | console.log(person.printNameFatArrow.bind(person)());
36 | console.log(person.printNameRegular());
37 | console.log(person.printName());
38 |
39 | // remember, Arrow functions
40 | // 1. cannot be used for Generators,
41 | // 2. do not get arguments object,
42 | // 3. cannot be used as constructors,
43 | // 4. call(), apply(), and bind() will not change the value of this
44 | };
45 |
46 | (context || this).demoLibs['arrow-func'] = demo;
47 | })(window);
48 |
--------------------------------------------------------------------------------
/async-await/index.js:
--------------------------------------------------------------------------------
1 | (function(context) {
2 |
3 | async function asyncFetchDemo() {
4 | console.log('Fetch async initiating');
5 | const responsePromise = await fetch('https://api.github.com/search/repositories?sort=stars&order=desc&q=art%20o%20fjs')
6 | const responseJSON = await responsePromise.json();
7 | console.log(responseJSON);
8 | console.log('Fetch async responsed successfully');
9 | }
10 |
11 | function regularFetchDemo() {
12 | console.log('Fetch regular initiating');
13 | fetch('https://api.github.com/search/repositories?sort=stars&order=desc&q=art%20o%20fjs')
14 | .then(x => x.json())
15 | .then(x => console.log(x));
16 | console.log('Fetch regular responsed successfully');
17 | }
18 |
19 | function getPromise(value) {
20 | return new Promise((resolve, reject) =>
21 | setTimeout(() =>
22 | resolve(value), 1000) );
23 | }
24 |
25 | async function asyncPromise() {
26 | // await can be only used in async functions
27 | console.log('asyncPromise initiated');
28 | const result1 = await getPromise(100);
29 | console.log('Result 1 recevied');
30 | const result2 = await getPromise(200);
31 | console.log('Result 2 recevied');
32 | console.log(result1 + result2);
33 | console.log('After result is printed');
34 | }
35 |
36 | function demo() {
37 | console.log('\n\nASYNC AWAIT DEMO');
38 | asyncFetchDemo();
39 | console.log('After asyncFetchDemo is called');
40 | regularFetchDemo();
41 | console.log('After regularFetchDemo is called');
42 | asyncPromise();
43 | };
44 |
45 | (context || this).demoLibs['async-await'] = demo;
46 | })(window);
47 |
--------------------------------------------------------------------------------
/spread/index.js:
--------------------------------------------------------------------------------
1 | (function(context) {
2 |
3 | function basicSpread() {
4 | const name = {
5 | name: {
6 | title: 'Dr.',
7 | firstName: 'Strange',
8 | lastName: '',
9 | }
10 | };
11 |
12 | const address = {
13 | address: {
14 | street: '890',
15 | locality: 'Fifth Avenue',
16 | city: 'Manhattan',
17 | state: 'New York',
18 | }
19 | };
20 |
21 | // This is object spread
22 | const employee2 = {
23 | ...name,
24 | ...address,
25 | id: 1234,
26 | };
27 | console.log(employee2);
28 |
29 | // This is object literal and not object spread
30 | const employee = {
31 | name,
32 | address,
33 | id: 1234,
34 | };
35 | console.log(employee);
36 |
37 | const arr1 = [1, 2, 3, 4];
38 | const arr2 = [10, 20, 30, 40];
39 | // spread
40 | const arrMerged = [...arr1, ...arr2];
41 |
42 | console.log(arrMerged);
43 | }
44 |
45 | function functionSpread() {
46 | // regular stuff
47 | print('John', 'Doe');
48 |
49 | // function spread
50 | const arrName = ['John', 'Doe'];
51 | print(...arrName);
52 |
53 | const a = 'John';
54 | const b = 'Doe';
55 | // now this is interesting, guess the output
56 | print(...[...a,...b]);
57 | }
58 |
59 | function print(firstName, lastName) {
60 | console.log(`Hey ${firstName} ${lastName}`);
61 | }
62 |
63 | function rest() {
64 | const colors = ['red', 'green', 'blue', 'yellow', 'brown'];
65 | // rest
66 | const [ first, second, ...restOfColors ] = colors;
67 | console.log(first);
68 | console.log(second);
69 | console.log(restOfColors);
70 | }
71 |
72 | function demo() {
73 | console.log('\n\nSPREAD');
74 | basicSpread();
75 | functionSpread();
76 | rest();
77 | };
78 |
79 | (context || this).demoLibs['spread'] = demo;
80 | })(window);
81 |
--------------------------------------------------------------------------------
/destruct/index.js:
--------------------------------------------------------------------------------
1 | (function(context) {
2 |
3 | function printAddress(address) {
4 | const {
5 | street,
6 | locality,
7 | city,
8 | state } = address;
9 | console.log(`${street}, ${locality}, ${city}, ${state}`);
10 | }
11 |
12 | function printName(name) {
13 | const { title, firstName, lastName } = name;
14 | console.log(`${title} ${firstName} ${lastName}`);
15 | }
16 |
17 | // destruct received object param
18 | function printNameDestructParams({ title, firstName, lastName }) {
19 | console.log(`${title} ${firstName} ${lastName}`);
20 | }
21 |
22 | function demo() {
23 | console.log('\n\nDESTRUCTURING');
24 |
25 | const employee = {
26 | id: '1234',
27 | name: {
28 | title: 'Dr.',
29 | firstName: 'Strange',
30 | lastName: ''
31 | },
32 | address: {
33 | street: '890',
34 | locality: 'Fifth Avenue',
35 | city: 'Manhattan',
36 | state: 'New York',
37 | }
38 | };
39 |
40 | const { id, name, address: addr } = employee;
41 |
42 | console.log(id);
43 | printName(name);
44 | printNameDestructParams(name);
45 | printAddress(addr);
46 |
47 | // array destructuring
48 | const arr = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
49 | // destructs arr[0], arr[1], arr[2] and rest of items into
50 | // mon tue wed and restOfNumbers respectively
51 | const [mon, tue, wed, ...restOfWeek] = arr;
52 | console.log(mon);
53 | console.log(tue);
54 | console.log(wed);
55 | console.log(restOfWeek);
56 |
57 | // destructs [0], [1] and rest of items into
58 | // first second and restOfNumbers respectively
59 | const [first, second, ...restOfNumbers] = [1, 2, 3, 4, 5];
60 | console.log(first);
61 | console.log(second);
62 | console.log(restOfNumbers);
63 | };
64 |
65 | (context || this).demoLibs['destruct'] = demo;
66 | })(window);
67 |
--------------------------------------------------------------------------------
/let-const-var/index.js:
--------------------------------------------------------------------------------
1 | (function(context) {
2 |
3 | var globalVar = 'global var';
4 | let globalLet = 'global let';
5 |
6 | function demoVsVar() {
7 | console.log(demoVarDeclaredLater);
8 | var demoVarDeclaredLater = 'demo var declared later';
9 |
10 | // console.log(demoLetDeclaredLater); Uncaught ReferenceError: demoVarDeclaredLater is not defined
11 | let demoLetDeclaredLater = 'demo var declared later';
12 |
13 | for (var i = 0; i < 5; i ++) {
14 | setTimeout(() => console.log(`value of var i: ${i}`), 100);
15 | }
16 |
17 | for (let j = 0; j < 5; j ++) {
18 | setTimeout(() => console.log(`value of let i: ${j}`), 100);
19 | }
20 | }
21 |
22 | function demo() {
23 | console.log('\n\nLET CONST VAR');
24 |
25 | globalVar = 'global var changed in method scope';
26 | console.log(globalVar);
27 | globalLet = 'global let changed in method scope';
28 | console.log(globalLet);
29 |
30 | /*
31 | If a global let is defined again in child scope, will cause error
32 | Uncaught ReferenceError: globalLet is not defined
33 | let globalLet = 'global Let';
34 | console.log(globalLet);
35 | */
36 |
37 | var demoVar = 'demo var';
38 | let demoLet = 'global let';
39 | const demoConst = 'I am constant';
40 |
41 | // let maintains block scope
42 | // var maintains function scope
43 |
44 | // It is a good practice to always declare variables as const
45 | // unless you need to re-assign it with new value later, in such cases use let
46 |
47 | console.log(demoVar);
48 | console.log(demoLet);
49 | console.log(demoConst);
50 |
51 | // demoConst = 'I am constant reassigned'; Uncaught TypeError: Assignment to constant variable.
52 |
53 | demoVsVar();
54 | };
55 |
56 | console.log(globalVar);
57 | console.log(globalLet);
58 |
59 | // console.log(demoVar); Uncaught ReferenceError: demoVar is not defined
60 |
61 | (context || this).demoLibs['let-const-var'] = demo;
62 | })(window);
63 |
--------------------------------------------------------------------------------
/proxies/index.js:
--------------------------------------------------------------------------------
1 | (function(context) {
2 |
3 | function demoSimpleProxy() {
4 | const target = {};
5 | const handler = {
6 | get: function(obj, key) {
7 | return obj[key];
8 | },
9 | set: function(obj, key, value) {
10 | if (key === 'age' && value < 21)
11 | throw Error('Age cannot be less than 21');
12 | else
13 | obj[key] = value;
14 | }
15 | };
16 | const prObj = new Proxy(target, handler);
17 | prObj.name = 'John';
18 | prObj.age = 21;
19 | // prObj.age = 19;
20 | console.log(prObj.name);
21 | console.log(prObj.age);
22 |
23 | // once in proxy target should not be accessed directly
24 | // here we just want to see what target actually prints
25 | // target is a regular object just accessed via proxy prObj
26 | console.log(target);
27 |
28 | // however, a proxy object wraps actual object in target
29 | // and access proxies in handler
30 | console.log(prObj);
31 |
32 | // does that mean accessing prObj.handler or prObj.target
33 | // will give us target and handler? NO.
34 | console.log(prObj.target); // undefined
35 | console.log(prObj.handler); // undefined
36 | }
37 |
38 | function createProxy(target, handler) {
39 | return new Proxy(target, handler);
40 | }
41 |
42 | function demoProxyCreator() {
43 | const myProxyObj = createProxy({}, {
44 | get: function(obj, key) { return obj[key]; },
45 | set: function(obj, key, value) { obj[key] = value; }
46 | });
47 | myProxyObj.name = 'Johny Boy';
48 | myProxyObj.language = 'English';
49 | console.log(myProxyObj.name);
50 | console.log(myProxyObj.language);
51 | }
52 |
53 | function demoRevocableProxy() {
54 | const { proxy, revoke } = Proxy.revocable({}, {}); // passing empty object as target and handler
55 | proxy.name = 'Sumeet Sarkar';
56 | console.log(proxy.name);
57 | revoke();
58 | console.log(proxy); // works, as Proxy still shows the entire object
59 | console.log(proxy.name); // error! TypeError: Cannot perform 'get' on a proxy that has been revoked
60 | }
61 |
62 | function demo() {
63 | console.log('\n\PROXIES');
64 | demoSimpleProxy();
65 | demoProxyCreator();
66 | demoRevocableProxy();
67 | };
68 |
69 | (context || this).demoLibs['proxies'] = demo;
70 | })(window);
71 |
--------------------------------------------------------------------------------
/bind-call-apply/index.js:
--------------------------------------------------------------------------------
1 | (function(context) {
2 |
3 | const personJohnDoe = {
4 | firstName: 'John',
5 | lastName: 'Doe',
6 | age: 28,
7 | getFullName: function() {
8 | console.log(`${this.firstName} ${this.lastName}`);
9 | }
10 | }
11 |
12 | const personJamesBond = {
13 | firstName: 'James',
14 | lastName: 'Bond',
15 | };
16 |
17 | function print(shouldIndent) {
18 | const lb = shouldIndent ? '\n' : '';
19 | console.log(`${this.firstName} ${lb}${this.lastName}, ${lb}${this.age}`);
20 | }
21 |
22 | function greet(language, firstName, lastName) {
23 | let greet = 'Hello';
24 | if (language === 'es') {
25 | greet = 'Hola';
26 | }
27 | console.log(`${greet}, ${firstName} ${lastName}`);
28 | }
29 |
30 | function bindDemo() {
31 | console.log('\nBIND ----------');
32 | print.bind(personJohnDoe)();
33 | personJohnDoe.getFullName();
34 | personJohnDoe.getFullName.bind(personJamesBond)();
35 | const printJohnDoeWithIndent = print.bind(personJohnDoe, true);
36 | printJohnDoeWithIndent();
37 | }
38 |
39 | function callDemo() {
40 | console.log('\nCALL ----------');
41 | print.call(personJohnDoe);
42 | print.call(personJohnDoe, true);
43 | personJohnDoe.getFullName.call(personJamesBond);
44 | }
45 |
46 | function applyDemo() {
47 | console.log('\nAPPLY ----------');
48 | print.apply(personJohnDoe);
49 | print.apply(personJohnDoe, [true]);
50 | greet.apply(this, ['es', 'Sumeet', 'Sarkar']);
51 |
52 | const arr1 = [1, 2, 3, 4];
53 | const arr2 = [5, 6, 7, 8];
54 | arr1.push.apply(arr1, arr2)
55 | console.log(arr1);
56 |
57 | console.log('name: ', getConfig('name'));
58 | console.log('server timeout: ', getConfig('server', 'timeout'));
59 | }
60 |
61 | function getConfig() {
62 | return getConfigWithCountryCode.apply(this, [countryCode, ...Array.from(arguments)]);
63 | }
64 |
65 | const countryCode = 'uk';
66 | const config = {
67 | 'us': {
68 | name: 'United States Of America',
69 | server: {
70 | timeout: '300'
71 | },
72 | },
73 | 'uk': {
74 | name: 'United Kingdom',
75 | server: {
76 | timeout: '500'
77 | }
78 | },
79 | }
80 |
81 | function getConfigWithCountryCode(countryCode = 'us', key1, key2) {
82 | const countryConfig = config[countryCode];
83 | if (key1 && key2)
84 | return countryConfig[key1] && countryConfig[key1][key2];
85 | return countryConfig[key1];
86 | }
87 |
88 | function demo() {
89 | console.log('\n\nBIND CALL APPLY');
90 | bindDemo();
91 | callDemo();
92 | applyDemo();
93 | };
94 |
95 | (context || this).demoLibs['bind-call-apply'] = demo;
96 | })(window);
97 |
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | window.demoLibs = {};
2 |
3 | const ulList = document.createElement('ul');
4 | ulList.setAttribute('id', 'parent-list');
5 | ulList.addEventListener("click", function(e) {
6 | if(e.target && e.target.nodeName === 'A') {
7 | window.demoLibs[e.target.id] && window.demoLibs[e.target.id]();
8 | }
9 | });
10 |
11 | document.body.appendChild(ulList);
12 |
13 | [
14 | {
15 | key: 'func-prog',
16 | name: 'Functional Programming',
17 | src: './func-prog/index.js',
18 | },{
19 | key: 'array-func',
20 | name: 'Array Functions',
21 | src: './array-func/index.js',
22 | },{
23 | key: 'arrow-func',
24 | name: 'Arrow Functions',
25 | src: './arrow-func/index.js',
26 | },{
27 | key: 'bind-call-apply',
28 | name: 'Bind Call Apply',
29 | src: './bind-call-apply/index.js',
30 | },{
31 | key: 'bind',
32 | name: 'Bind In Class',
33 | src: './bind-in-es5class/index.js',
34 | },{
35 | key: 'let-const-var',
36 | name: 'Let Const Var',
37 | src: './let-const-var/index.js',
38 | },{
39 | key: 'destruct',
40 | name: 'Destructuring',
41 | src: './destruct/index.js',
42 | },{
43 | key: 'spread',
44 | name: 'Spread',
45 | src: './spread/index.js',
46 | },{
47 | key: 'promises',
48 | name: 'Promises',
49 | src: './promises/index.js',
50 | },{
51 | key: 'default-params',
52 | name: 'Default Parameters',
53 | src: './default-params/index.js',
54 | },{
55 | key: 'template-literals',
56 | name: 'Template Literals',
57 | src: './template-literals/index.js',
58 | },{
59 | key: 'object-literals',
60 | name: 'Object Literals',
61 | src: './object-literals/index.js',
62 | },{
63 | key: 'func-curry',
64 | name: 'Function Currying',
65 | src: './func-curry/index.js',
66 | },{
67 | key: 'closures',
68 | name: 'Closures',
69 | src: './closures/index.js',
70 | },{
71 | key: 'proxies',
72 | name: 'Proxies',
73 | src: './proxies/index.js',
74 | },{
75 | key: 'async-await',
76 | name: 'Async Await',
77 | src: './async-await/index.js',
78 | },{
79 | key: 'generators',
80 | name: 'Generators',
81 | src: './generators/index.js',
82 | },
83 | ].sort((a, b) => {
84 | const nameA = a.name.toLowerCase();
85 | const nameB = b.name.toLowerCase();
86 | if (nameA < nameB) return -1;
87 | else if (nameA > nameB) return 1;
88 | else return 0;
89 |
90 | }).forEach(item => {
91 | const li = document.createElement('li');
92 | const a = document.createElement('a');
93 | a.setAttribute('id', item.key);
94 | a.setAttribute('href', '#');
95 | a.text = item.name;
96 | li.appendChild(a);
97 | ulList.appendChild(li);
98 | if (item.src) {
99 | const script = document.createElement('script');
100 | script.type = 'text/javascript';
101 | script.src = item.src;
102 | document.body.appendChild(script);
103 | }
104 | });
105 |
--------------------------------------------------------------------------------
/array-func/index.js:
--------------------------------------------------------------------------------
1 | (function(context) {
2 |
3 | function demoForEach(items, func) {
4 | // Use of Arrow function
5 | items.forEach(func || (item => console.log(item)));
6 | }
7 |
8 | function demoFilter(items, func) {
9 | // Use of Arrow function
10 | return items.filter(func || (item => item.type === 'veg'));
11 | }
12 |
13 | function demoMap(items) {
14 | return items.map(item => {
15 | // Use of template string literals
16 | item.name = `chopped: ${item.name}`;
17 | return item;
18 | });
19 | }
20 |
21 | function demoReduce(bread, fillings, sauce) {
22 | const initial = { sandwich: {
23 | bread: bread,
24 | sauce: sauce,
25 | fillings: []
26 | }};
27 |
28 | return fillings.reduce((res, item) => {
29 | res.sandwich.fillings.push(item.name);
30 | return res;
31 | }, initial);
32 | }
33 |
34 | function demo() {
35 | console.log('\n\nARRAY FUNCTIONS');
36 |
37 | const breads = [
38 | 'Wheat bread',
39 | 'Honey oat bread',
40 | ];
41 |
42 | const sauces = [
43 | 'Mayo',
44 | 'Mustard',
45 | 'Mint'
46 | ];
47 |
48 | const fillings = [
49 | {
50 | 'name': 'Cheese',
51 | 'type': 'veg'
52 | },
53 | {
54 | 'name': 'Cucumber',
55 | 'type': 'veg'
56 | },
57 | {
58 | 'name': 'Tomatoes',
59 | 'type': 'veg'
60 | },
61 | {
62 | 'name': 'Chicken',
63 | 'type': 'non-veg'
64 | },
65 | {
66 | 'name': 'Lettuce',
67 | 'type': 'veg'
68 | }
69 | ];
70 |
71 | console.log('Available Ingredients -----------------');
72 | console.log('Breads -----------------');
73 | demoForEach(breads);
74 | console.log('Fillings ---------------');
75 | demoForEach(fillings);
76 | console.log('Sauces -----------------');
77 | demoForEach(sauces);
78 |
79 | const bread = demoFilter(breads, b => b === 'Wheat bread');
80 | const sauce = demoFilter(sauces, b => b === 'Mustard');
81 |
82 | const vegFillings = demoFilter(fillings);
83 | const choppedFillings = demoMap(vegFillings);
84 |
85 | console.log('Final Ingredients -----------------');
86 | demoForEach(bread);
87 | demoForEach(vegFillings, f => console.log(f.name));
88 | demoForEach(sauce);
89 |
90 | /**
91 | * Expected output
92 | * {
93 | * sandwich: {
94 | * bread: '...',
95 | * fillings: [ item1, item2, ...]
96 | * sauce: [...]
97 | * }
98 | * }
99 | */
100 |
101 | const sandwich = demoReduce(bread, choppedFillings, sauce);
102 |
103 | console.log('Here is your Sandwich! -----------------');
104 | console.log(sandwich);
105 |
106 | reduceExampleExtra();
107 |
108 | demoSome();
109 | demoEvery();
110 | demoFrom('a', 'b', 1, 2, { a: 'a' });
111 | demoOf();
112 | };
113 |
114 | function demoSome() {
115 | const numbers = [1, 2, 3, 4, 5, 6, 7];
116 | console.log(numbers.some(x => x % 2 === 0));
117 | }
118 |
119 | function demoEvery() {
120 | const numbers = [1, 2, 3, 4, 5, 6, 7];
121 | console.log(numbers.every(x => x % 2 === 0));
122 | }
123 |
124 | function demoFrom() {
125 | console.log(Array.from([1, 2, 3, 4]));
126 | // Uncaught TypeError: arguments.forEach is not a function
127 | // because arguments is not any array
128 | // arguments.forEach(x => console.log(x));
129 | // instead use Array.from
130 | const arrArgs = Array.from(arguments);
131 | arrArgs.forEach(x => console.log(x));
132 |
133 | // use case of Array from using optional map function argument
134 | console.log(Array.from([1, 2, 3, 4], x => x * 2));
135 | }
136 |
137 | function demoOf() {
138 | console.log(Array.of(1, 2, 3, 4, 5, 6));
139 | }
140 |
141 | function reduceExampleExtra() {
142 | const input = [
143 | {
144 | id: '1234',
145 | 'name': 'John Doe',
146 | 'age': 27,
147 | },{
148 | id: '5678',
149 | 'name': 'James Bond',
150 | 'age': 31,
151 | },
152 | ];
153 | const output = input.reduce((acc, emp) => {
154 | // Use of object destructuring
155 | const { name, age } = emp;
156 | // Use of object literals
157 | acc[emp.id] = { name, age };
158 | return acc;
159 | }, {});
160 |
161 | console.log(input);
162 | console.log(output);
163 | }
164 |
165 | (context || this).demoLibs['array-func'] = demo;
166 | })(window);
167 |
--------------------------------------------------------------------------------