├── .gitignore ├── 10-Modules ├── 1-1 │ ├── app.js │ ├── index.html │ └── index.js ├── 1-2 │ ├── app.js │ ├── index.html │ └── math.js ├── 2-1 │ ├── app.js │ ├── index.html │ └── stats.js ├── 2-2 │ └── app.js ├── 3-1 │ ├── app.js │ └── index.js └── 3-2 │ ├── app.js │ ├── index.html │ └── index.js ├── 11-Library ├── app1.js ├── app10.js ├── app11.js ├── app12.js ├── app13.js ├── app14.js ├── app15.js ├── app16.js ├── app2.js ├── app3.js ├── app4.js ├── app5.js ├── app6.js ├── app7.js ├── app8.js ├── app9.js └── index.html ├── 12-Iterators&Generators ├── app1.js ├── app10.js ├── app11.js ├── app2.js ├── app3.js ├── app4.js ├── app5.js ├── app6.js ├── app7.js ├── app8.js ├── app9.js └── index.html ├── 13-AsynchronousJS ├── 1-1 │ ├── app1.js │ ├── app2.js │ ├── app3.js │ └── index.html ├── 1-2 │ ├── Dweb.png │ ├── INU.png │ └── index.html ├── 1-3 │ ├── app.js │ ├── db.json │ └── index.html ├── 1-4 │ ├── app1.js │ ├── app2.js │ └── config.json ├── 1-5 │ ├── app1.js │ ├── app2.js │ └── incheon.txt ├── 1-6 │ ├── a.txt │ ├── app1.js │ ├── app2.js │ └── b.txt ├── 2-1 │ ├── app1.js │ ├── app2.js │ ├── db.json │ └── index.html ├── 2-2 │ ├── app1.js │ ├── app2.js │ ├── app3.js │ ├── app4.js │ ├── app5.js │ ├── db.json │ └── index.html ├── 2-3 │ ├── app1.js │ ├── db.json │ ├── flow.png │ └── index.html ├── 2-4 │ ├── app1.js │ ├── app2.js │ ├── app3.js │ ├── app4.js │ └── index.html ├── 2-5 │ ├── app1.js │ └── index.html ├── 2-6 │ ├── app1.js │ ├── app2.js │ ├── app3.js │ ├── app4.js │ ├── app5.js │ ├── db.json │ └── index.html ├── 3-1 │ ├── app1.js │ ├── app2.js │ ├── app3.js │ ├── app4.js │ ├── app5.js │ ├── db.json │ └── index.html └── ex-promises │ ├── events.js │ ├── promise1.js │ ├── promise2.js │ └── promise3.js ├── 15-WebBrowser ├── 1-1 │ └── index.html ├── 11-1 │ ├── app1.js │ ├── app2.js │ ├── app3.js │ ├── app4.js │ ├── app5.html │ ├── app5.js │ ├── app6.js │ ├── app8.html │ ├── app8.js │ ├── db.json │ ├── index.html │ └── uni.jpg ├── 11-2 │ ├── chatServer.js │ └── index.html ├── 11-3 │ ├── index.html │ └── server.js ├── 12-1 │ ├── app1.js │ ├── app2.js │ ├── app3.js │ └── index.html ├── 12-2 │ ├── app1.js │ ├── app2.js │ └── index.html ├── 12-3 │ ├── app1.js │ ├── app2.js │ ├── app3.js │ ├── app4.js │ ├── app5.js │ └── index.html ├── 12-4 │ └── index.html └── 8-1 │ ├── blue-robot.png │ ├── index1.html │ ├── index2.html │ └── index3.html ├── 6-Object ├── app1.js ├── app10.js ├── app11.js ├── app12.js ├── app13.js ├── app14.js ├── app15.js ├── app16.js ├── app17.js ├── app18.js ├── app19.js ├── app2.js ├── app20.js ├── app21.js ├── app22.js ├── app23.js ├── app3.js ├── app4.js ├── app5.js ├── app6.js ├── app7.js ├── app8.js ├── app9.js └── index.html ├── 7-Arrays ├── app1.js ├── app10.js ├── app11.js ├── app12.js ├── app13.js ├── app14.js ├── app15.js ├── app16.js ├── app17.js ├── app18.js ├── app19.js ├── app2.js ├── app20.js ├── app21.js ├── app22.js ├── app23.js ├── app24.js ├── app25.js ├── app3.js ├── app4.js ├── app5.js ├── app6.js ├── app7.js ├── app8.js ├── app9.js └── index.html ├── 8-Functions ├── app1.js ├── app10.js ├── app11.js ├── app12.js ├── app14.js ├── app15.js ├── app16.js ├── app17.js ├── app18.js ├── app19.js ├── app2.js ├── app20.js ├── app21.js ├── app22.js ├── app23.js ├── app24.js ├── app25.js ├── app26.js ├── app27.js ├── app28.js ├── app29.js ├── app3.js ├── app30.js ├── app31.js ├── app32.js ├── app33.js ├── app4.js ├── app5.js ├── app6.js ├── app7.js ├── app8.js ├── app9.js └── index.html ├── 9-Classes ├── app1.js ├── app2.js ├── app3.js ├── app4.js ├── app5.js ├── app6.js ├── app7.js └── index.html ├── Appendix-React ├── app.js └── index.html ├── Appendix-TypeScript ├── app1.js ├── app2.js ├── app2.ts ├── app3.js ├── app3.ts ├── app4.js ├── app4.ts ├── greeter.js ├── greeter.ts └── index.html ├── README.md ├── images ├── Dweb.png └── INU.png ├── index.html ├── package-lock.json ├── package.json ├── tsconfig.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | .pnpm-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | *.lcov 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # Snowpack dependency directory (https://snowpack.dev/) 46 | web_modules/ 47 | 48 | # TypeScript cache 49 | *.tsbuildinfo 50 | 51 | # Optional npm cache directory 52 | .npm 53 | 54 | # Optional eslint cache 55 | .eslintcache 56 | 57 | # Optional stylelint cache 58 | .stylelintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variable files 76 | .env 77 | .env.development.local 78 | .env.test.local 79 | .env.production.local 80 | .env.local 81 | 82 | # parcel-bundler cache (https://parceljs.org/) 83 | .cache 84 | .parcel-cache 85 | 86 | # Next.js build output 87 | .next 88 | out 89 | 90 | # Nuxt.js build / generate output 91 | .nuxt 92 | dist 93 | 94 | # Gatsby files 95 | .cache/ 96 | # Comment in the public line in if your project uses Gatsby and not Next.js 97 | # https://nextjs.org/blog/next-9-1#public-directory-support 98 | # public 99 | 100 | # vuepress build output 101 | .vuepress/dist 102 | 103 | # vuepress v2.x temp and cache directory 104 | .temp 105 | .cache 106 | 107 | # Docusaurus cache and generated files 108 | .docusaurus 109 | 110 | # Serverless directories 111 | .serverless/ 112 | 113 | # FuseBox cache 114 | .fusebox/ 115 | 116 | # DynamoDB Local files 117 | .dynamodb/ 118 | 119 | # TernJS port file 120 | .tern-port 121 | 122 | # Stores VSCode versions used for testing VSCode extensions 123 | .vscode-test 124 | 125 | # yarn v2 126 | .yarn/cache 127 | .yarn/unplugged 128 | .yarn/build-state.yml 129 | .yarn/install-state.gz 130 | .pnp.* -------------------------------------------------------------------------------- /10-Modules/1-1/app.js: -------------------------------------------------------------------------------- 1 | // 10.1.1 Automating Closure-Based Modularity 2 | 3 | const modules = {}; 4 | function require(moduleName) { 5 | return modules[moduleName]; 6 | } 7 | 8 | modules["sets.js"] = (function () { 9 | const exports = {}; 10 | exports.BitSet = class BitSet { 11 | arr = []; 12 | insert(v) { 13 | this.arr.push(v); 14 | console.log(v); 15 | } 16 | }; 17 | return exports; 18 | })(); 19 | 20 | modules["stats.js"] = (function () { 21 | const exports = {}; 22 | const sum = (x, y) => x + y; 23 | const square = (x) => x * x; 24 | exports.mean = function (data) { 25 | let sum = 0; 26 | for (let v of data) { 27 | sum += v; 28 | } 29 | return sum / data.length; 30 | }; 31 | exports.stddev = function (data) {}; 32 | return exports; 33 | })(); 34 | -------------------------------------------------------------------------------- /10-Modules/1-1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ✨✨ Chapter 10. Modules 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /10-Modules/1-1/index.js: -------------------------------------------------------------------------------- 1 | const bitSet = require("sets.js").BitSet; 2 | const stats = require("stats.js"); 3 | 4 | let s = new bitSet(); 5 | s.insert(10); 6 | s.insert(20); 7 | s.insert(30); 8 | let average = stats.mean([...s.arr]); // average is 20 9 | console.log(average); 10 | -------------------------------------------------------------------------------- /10-Modules/1-2/app.js: -------------------------------------------------------------------------------- 1 | let s = sum(1, 3); 2 | console.log(sum(199, 324)); 3 | -------------------------------------------------------------------------------- /10-Modules/1-2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ✨✨ Chapter 10. Modules 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /10-Modules/1-2/math.js: -------------------------------------------------------------------------------- 1 | function sum(x, y) { 2 | return x + y; 3 | } 4 | -------------------------------------------------------------------------------- /10-Modules/2-1/app.js: -------------------------------------------------------------------------------- 1 | // Import the entire stats object, with all of its functions 2 | const stats = require("./stats.js"); 3 | 4 | let data = [1, 10, 11]; 5 | // We've got more functions than we need, but they're neatly 6 | // organized into a convenient "stats" namespace. 7 | let average = stats.mean(data); 8 | console.log("👏avg", average); 9 | 10 | // Alternatively, we can use idiomatic destructuring assignment to import 11 | // exactly the functions we want directly into the local namespace: 12 | const { stddev } = require("./stats.js"); 13 | // This is nice and succinct, though we lose a bit of context 14 | // without the 'stats' prefix as a namspace for the stddev() function. 15 | let sd = stddev(data); 16 | console.log("👏sd", sd); 17 | -------------------------------------------------------------------------------- /10-Modules/2-1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ✨✨ Chapter 10. Modules 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /10-Modules/2-1/stats.js: -------------------------------------------------------------------------------- 1 | // Define all the functions, public and private 2 | const sum = (x, y) => x + y; 3 | const square = (x) => x * x; 4 | const mean = (data) => data.reduce(sum) / data.length; 5 | const stddev = (d) => { 6 | let m = mean(d); 7 | return Math.sqrt( 8 | d 9 | .map((x) => x - m) 10 | .map(square) 11 | .reduce(sum) / 12 | (d.length - 1) 13 | ); 14 | }; 15 | // 🌟🌟 Now export only the public ones 16 | module.exports = { mean, stddev }; 17 | -------------------------------------------------------------------------------- /10-Modules/2-2/app.js: -------------------------------------------------------------------------------- 1 | // 🌟 10.2.2 Node Imports 2 | 3 | // These modules are built in to Node 4 | const fs = require("fs"); // The built-in filesystem module 5 | const http = require("http"); // The built-in HTTP module 6 | // // The Express HTTP server framework is a third-party module. 7 | // // It is not part of Node but has been installed locally 8 | const express = require("express"); 9 | -------------------------------------------------------------------------------- /10-Modules/3-1/app.js: -------------------------------------------------------------------------------- 1 | // 🌟 10.3 Modules in ES6 2 | // 🌟 10.3.1 ES6 Exports 3 | 4 | const PI = Math.PI; 5 | function degreesToRadians(d) { 6 | return (d * PI) / 180; 7 | } 8 | class Circle { 9 | constructor(r) { 10 | this.r = r; 11 | } 12 | area() { 13 | return PI * this.r * this.r; 14 | } 15 | } 16 | 17 | export { Circle, degreesToRadians, PI }; 18 | -------------------------------------------------------------------------------- /10-Modules/3-1/index.js: -------------------------------------------------------------------------------- 1 | //import {Circle} from "./app.js"; 2 | //import elems from "./app.js"; 3 | 4 | import * as elems from "./app.js"; 5 | 6 | let circle = new elems.Circle(10); 7 | console.log(`⛔️`, circle.area()); 8 | -------------------------------------------------------------------------------- /10-Modules/3-2/app.js: -------------------------------------------------------------------------------- 1 | // 🌟 10.3 Modules in ES6 2 | // 🌟 10.3.1 ES6 Exports 3 | 4 | const PI = Math.PI; 5 | function degreesToRadians(d) { 6 | return (d * PI) / 180; 7 | } 8 | class Circle { 9 | constructor(r) { 10 | this.r = r; 11 | } 12 | area() { 13 | return PI * this.r * this.r; 14 | } 15 | } 16 | 17 | export { Circle, degreesToRadians, PI }; 18 | -------------------------------------------------------------------------------- /10-Modules/3-2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ✨✨ Chapter 10. Modules 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /10-Modules/3-2/index.js: -------------------------------------------------------------------------------- 1 | //import {Circle} from "./app.js"; 2 | //import elems from "./app.js"; 3 | 4 | import * as elems from "./app.js"; 5 | 6 | let circle = new elems.Circle(10); 7 | console.log(`👏`, circle.area()); 8 | -------------------------------------------------------------------------------- /11-Library/app1.js: -------------------------------------------------------------------------------- 1 | // ✨ 11.1.1 The Set Class 2 | "use strict"; 3 | 4 | let s = new Set(); // A new, empty set 5 | let t = new Set([1, s]); // A new set with two members 6 | 7 | let t1 = new Set(s); // A new set that copies the elements of s. 8 | let unique = new Set("Mississippi"); // 4 elements: "M", "i", "s", and "p" 9 | 10 | console.log(unique.size); // => 4 11 | -------------------------------------------------------------------------------- /11-Library/app10.js: -------------------------------------------------------------------------------- 1 | // ✨ 11.1.2 The Map Class 2 | 3 | let m = new Map(); // Start with an empty map 4 | m.size; // => 0: empty maps have no keys 5 | m.set("one", 1); 6 | m.set("two", 2); 7 | m.size; 8 | m.get("two"); // => 2: return the value associated with key "two" 9 | m.get("three"); 10 | set; 11 | m.set("one", true); // Change the value associated with an existing key 12 | m.size; 13 | m.has("one"); 14 | m.has(true); //false: the map does not have a key true 15 | m.delete("one"); 16 | m.size; 17 | m.delete("three"); // false: failed to delete a nonexistent key 18 | m.clear(); 19 | -------------------------------------------------------------------------------- /11-Library/app11.js: -------------------------------------------------------------------------------- 1 | // ✨ 11.1.2 The Map Class 2 | 3 | let m = new Map().set("one", 1).set("two", 2).set("three", 3); 4 | m.size; // => 3 5 | m.get("two"); // => 2 6 | -------------------------------------------------------------------------------- /11-Library/app12.js: -------------------------------------------------------------------------------- 1 | // ✨ 11.1.2 The Map Class 2 | 3 | let m = new Map(); // Start with an empty map. 4 | m.set({}, 1); // Map one empty object to the number 1. 5 | m.set({}, 2); // Map a different empty object to the number 2. 6 | m.size; // => 2: there are two keys in this map 7 | m.get({}); // => undefined: but this empty object is not a key 8 | m.set(m, undefined); // Map the map itself to the value undefined. 9 | m.has(m); // => true: m is a key in itself 10 | m.get(m); // => undefined: same value we'd get if m wasn't a key 11 | -------------------------------------------------------------------------------- /11-Library/app13.js: -------------------------------------------------------------------------------- 1 | // ✨ 11.1.2 The Map Class 2 | 3 | let m = new Map([ 4 | ["x", 1], 5 | ["y", 2], 6 | ]); 7 | [...m]; // => [["x", 1], ["y", 2]] 8 | 9 | for (let [key, value] of m) { 10 | // On the first iteration, key will be "x" and value will be 1 11 | // On the second iteration, key will be "y" and value will be 2 12 | } 13 | -------------------------------------------------------------------------------- /11-Library/app14.js: -------------------------------------------------------------------------------- 1 | // ✨ 11.1.2 The Map Class 2 | 3 | let m = new Map([ 4 | ["x", 1], 5 | ["y", 2], 6 | ]); 7 | 8 | [...m.keys()]; // => ["x", "y"]: just the keys 9 | [...m.values()]; // => [1, 2]: just the values 10 | [...m.entries()]; // => [["x", 1], ["y", 2]]: same as [...m] 11 | -------------------------------------------------------------------------------- /11-Library/app15.js: -------------------------------------------------------------------------------- 1 | // ✨ 11.1.2 The Map Class 2 | 3 | let m = new Map([ 4 | ["x", 1], 5 | ["y", 2], 6 | ]); 7 | 8 | m.forEach((value, key) => { 9 | console.log(`🔑 ${key} : 💕 ${value}`); 10 | // note value, key NOT key, value 11 | // On the first invocation, value will be 1 and key will be "x" 12 | // On the second invocation, value will be 2 and key will be "y" 13 | }); 14 | -------------------------------------------------------------------------------- /11-Library/app16.js: -------------------------------------------------------------------------------- 1 | function getRectArea(width, height) { 2 | if (isNaN(width) || isNaN(height)) { 3 | throw new Error("Parameter is not a number!"); 4 | } else { 5 | return width * height; 6 | } 7 | } 8 | 9 | try { 10 | getRectArea(3, "A"); 11 | } catch (e) { 12 | console.error(e); 13 | // console.error(e.name); 14 | // console.error(e.message); 15 | // console.error(e.toString()); 16 | // Expected output: Error: Parameter is not a number! 17 | } 18 | 19 | let s = getRectArea(5, 10); 20 | console.log(`💕 ${s}`); 21 | -------------------------------------------------------------------------------- /11-Library/app2.js: -------------------------------------------------------------------------------- 1 | // ✨ Enumerable & Iterable Object 2 | "use strict"; 3 | 4 | let obj = { univ: "Incheon National Univ", location: "Songdo" }; 5 | 6 | // enumerable이 false인 경우 출력되지 않음 7 | /* 8 | Object.defineProperty(obj, "univ", { 9 | enumerable: false, 10 | }); 11 | */ 12 | 13 | for (let key in obj) { 14 | console.log(obj[key]); 15 | } 16 | 17 | console.log(Object.getOwnPropertyDescriptor(obj, "univ")); 18 | -------------------------------------------------------------------------------- /11-Library/app3.js: -------------------------------------------------------------------------------- 1 | // ✨ Enumerable & Iterable Object 2 | 3 | let arr = [2, 3, 4, 5]; 4 | for (let docs of arr) { 5 | console.log(docs); 6 | } 7 | 8 | console.log(arr[Symbol.iterator]()); 9 | 10 | let obj = { x: 1, y: 2 }; 11 | 12 | let str = "dweb"; 13 | for (let c of str) { 14 | console.log(c); 15 | } 16 | -------------------------------------------------------------------------------- /11-Library/app4.js: -------------------------------------------------------------------------------- 1 | // ✨ 11.1.1 The Set Class 2 | "use strict"; 3 | 4 | let s = new Set(); // Start empty 5 | s.size; // => 0 6 | s.add(1); // Add a number 7 | s.size; // => 1; now the set has one member 8 | s.add(1); // Add the same number again 9 | s.size; // => 1; the size does not change 10 | s.add(true); // Add another value; note that it is fine to mix types 11 | s.size; // => 2 12 | s.add([1, 2, 3]); // Add an array value 13 | s.size; // => 3; the array was added, not its elements 14 | s.delete(1); // => true: successfully deleted element 1 15 | s.size; // => 2: the size is back down to 2 16 | s.delete("test"); // => false: "test" was not a member, deletion failed 17 | s.delete(true); // => true: delete succeeded 18 | s.delete([1, 2, 3]); // => false: the array in the set is different 19 | s.size; // => 1: there is still that one array in the set 20 | s.clear(); // Remove everything from the set 21 | s.size; // => 0 22 | 23 | // ✨ 여러 값을 add 하고 싶다면, chained method calls을 사용 24 | s.add("a").add("b").add("c"); 25 | -------------------------------------------------------------------------------- /11-Library/app5.js: -------------------------------------------------------------------------------- 1 | // ✨ 11.1.1 The Set Class 2 | "use strict"; 3 | 4 | let oneDigitPrimes = new Set([2, 3, 5, 7]); 5 | oneDigitPrimes.has(2); // => true: 2 is a one-digit prime number 6 | oneDigitPrimes.has(3); // => true: so is 3 7 | oneDigitPrimes.has(4); // => false: 4 is not a prime 8 | oneDigitPrimes.has("5"); // => false: "5" is not even a number 9 | -------------------------------------------------------------------------------- /11-Library/app6.js: -------------------------------------------------------------------------------- 1 | // ✨ 11.1.1 The Set Class 2 | "use strict"; 3 | let oneDigitPrimes = new Set([2, 3, 5, 7]); 4 | let sum = 0; 5 | for (let p of oneDigitPrimes) { 6 | // Loop through the one-digit primes 7 | sum += p; // and add them up 8 | } 9 | sum; // => 17: 2 + 3 + 5 + 7 10 | 11 | [...oneDigitPrimes]; // => [2,3,5,7]: the set converted to an Array 12 | Math.max(...oneDigitPrimes); // => 7: set elements passed as function arguments 13 | -------------------------------------------------------------------------------- /11-Library/app7.js: -------------------------------------------------------------------------------- 1 | // ✨ 11.1.1 The Set Class 2 | 3 | "use strict"; 4 | let oneDigitPrimes = new Set([2, 3, 5, 7]); 5 | let product = 1; 6 | oneDigitPrimes.forEach((n) => { 7 | product *= n; 8 | }); 9 | product; // => 210: 2 * 3 * 5 * 7 10 | 11 | let numbers = [10, 11, 12, 13]; 12 | numbers.forEach(function (number, idx) { 13 | console.log(number, idx); 14 | }); 15 | -------------------------------------------------------------------------------- /11-Library/app8.js: -------------------------------------------------------------------------------- 1 | // ✨ 11.1.2 The Map Class 2 | 3 | let m = new Map(); // Create a new, empty map 4 | let n = new Map([ 5 | // A new map initialized with string keys mapped to numbers 6 | ["one", 1], 7 | ["two", 2], 8 | ]); 9 | -------------------------------------------------------------------------------- /11-Library/app9.js: -------------------------------------------------------------------------------- 1 | // ✨ 11.1.2 The Map Class 2 | 3 | let n = new Map([ 4 | // A new map initialized with string keys mapped to numbers 5 | ["one", 1], 6 | ["two", 2], 7 | ]); 8 | 9 | let copy = new Map(n); // A new map with the same keys and values as map n 10 | let o = { x: 1, y: 2 }; // An object with two properties 11 | let p = new Map(Object.entries(o)); // Same as new map([["x", 1], ["y", 2]]) 12 | -------------------------------------------------------------------------------- /11-Library/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ✨✨ Chapter 11. The JavaScript Standard Library 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /12-Iterators&Generators/app1.js: -------------------------------------------------------------------------------- 1 | // ✨ 예시 1. 2 | let sum = 0; 3 | for (let i of [1, 2, 3]) { 4 | // Loop once for each of these values 5 | sum += i; 6 | } 7 | sum; // => 6 8 | 9 | // ✨ 예시 2. 10 | let chars = [..."abcd"]; // chars == ["a", "b", "c", "d"] 11 | let data = [1, 2, 3, 4, 5]; 12 | Math.max(...data); // => 5 13 | 14 | // ✨ 예시 3. 15 | let purpleHaze = Uint8Array.of(255, 0, 255, 128); 16 | let [r, g, b, a] = purpleHaze; // a == 128 17 | 18 | // ✨ 예시 4. 19 | let m = new Map([ 20 | ["one", 1], 21 | ["two", 2], 22 | ]); 23 | for (let [k, v] of m) console.log(k, v); // Logs 'one 1' and 'two 2' 24 | 25 | // ✨ 예시 5. 26 | [...m]; // => [["one", 1], ["two", 2]]: default iteration 27 | [...m.entries()]; // => [["one", 1], ["two", 2]]: entries() method is the same 28 | [...m.keys()]; // => ["one", "two"]: keys() method iterates just map keys 29 | [...m.values()]; // => [1, 2]: values() method iterates just map values 30 | 31 | // ✨ 예시 6. 32 | // Strings are iterable, so the two sets are the same: 33 | new Set("abc"); // => new Set(["a", "b", "c"]) 34 | -------------------------------------------------------------------------------- /12-Iterators&Generators/app10.js: -------------------------------------------------------------------------------- 1 | // 🌟 yield* and Recursive Generators 2 | 3 | // A generator function that yields the set of one digit (base-10) primes. 4 | function* oneDigitPrimes() { 5 | // Invoking this function does not run the code 6 | yield 2; // but just returns a generator object. Calling 7 | yield 3; // the next() method of that generator runs 8 | yield 5; // the code until a yield statement provides 9 | yield 7; // the return value for the next() method. 10 | } 11 | 12 | function* sequence(...iterables) { 13 | for (let iterable of iterables) { 14 | for (let item of iterable) { 15 | yield item; 16 | } 17 | } 18 | } 19 | console.log([...sequence("abc", oneDigitPrimes())]); // => ["a","b","c",2,3,5,7] 20 | -------------------------------------------------------------------------------- /12-Iterators&Generators/app11.js: -------------------------------------------------------------------------------- 1 | // 🌟 yield* and Recursive Generators 2 | 3 | function* oneDigitPrimes() { 4 | // Invoking this function does not run the code 5 | yield 2; // but just returns a generator object. Calling 6 | yield 3; // the next() method of that generator runs 7 | yield 5; // the code until a yield statement provides 8 | yield 7; // the return value for the next() method. 9 | } 10 | 11 | // 🌟 The yield* keyword 12 | // - iterable object를 반복하여 각각의 결과값으로 이루어진 하나의 "Generator"를 반환 13 | 14 | function* sequence(...iterables) { 15 | for (let iterable of iterables) { 16 | yield* iterable; 17 | } 18 | } 19 | console.log([...sequence("abc", oneDigitPrimes())]); // => ["a","b","c",2,3,5,7] 20 | 21 | // console.log(sequence("abc")); // => ["a","b","c"] 22 | -------------------------------------------------------------------------------- /12-Iterators&Generators/app2.js: -------------------------------------------------------------------------------- 1 | // ✨ How Iterators Work 2 | 3 | let iterable = [99]; 4 | let iterator = iterable[Symbol.iterator](); 5 | for (let result = iterator.next(); !result.done; result = iterator.next()) { 6 | console.log(result.value); // result.value == 99 7 | } 8 | 9 | let list = [1, 2, 3, 4, 5]; 10 | let iter = list[Symbol.iterator](); 11 | let head = iter.next().value; // head == 1 12 | iter.next(); 13 | let tail = [...iter]; // tail == [2,3,4,5] 14 | console.log(tail); 15 | -------------------------------------------------------------------------------- /12-Iterators&Generators/app3.js: -------------------------------------------------------------------------------- 1 | // 🌟 Generators 2 | 3 | // A generator function that yields the set of one digit (base-10) primes. 4 | function* oneDigitPrimes() { 5 | // Invoking this function does not run the code 6 | yield 2; // but just returns a generator object. Calling 7 | yield 3; // the next() method of that generator runs 8 | yield 5; // the code until a yield statement provides 9 | yield 7; // the return value for the next() method. 10 | } 11 | 12 | // When we invoke the generator function, we get a generator 13 | let primes = oneDigitPrimes(); 14 | 15 | // A generator is an iterator object that iterates the yielded values 16 | primes.next().value; //=>2 17 | primes.next().value; //=>3 18 | primes.next().value; //=>5 19 | primes.next().value; //=>7 20 | primes.next().done; // => true 21 | 22 | // Generators have a Symbol.iterator method to make them iterable 23 | primes[Symbol.iterator](); // => primes 24 | 25 | [...oneDigitPrimes()]; // => [2,3,5,7] 26 | let sum = 0; 27 | for (let prime of oneDigitPrimes()) sum += prime; 28 | sum; // => 17 29 | -------------------------------------------------------------------------------- /12-Iterators&Generators/app4.js: -------------------------------------------------------------------------------- 1 | // 🌟 Generators 2 | 3 | const seq = function* (from, to) { 4 | for (let i = from; i <= to; i++) yield i; 5 | }; 6 | // 👍 [Symbol.Iterator] 메서드를 가짐. 따라서 ... spread operator 사용도 가능 7 | [...seq(3, 5)]; // => [3, 4, 5] 8 | 9 | // 👍 [Symbol.Iterator] 메서드를 가짐. 따라서 ... for/of 사용도 가능 10 | const gen = seq(1, 10); 11 | let sum = 0; 12 | for (let i of gen) { 13 | sum += i; 14 | } 15 | -------------------------------------------------------------------------------- /12-Iterators&Generators/app5.js: -------------------------------------------------------------------------------- 1 | // 🌟 Generators 2 | 3 | let o = { 4 | x: 1, 5 | y: 2, 6 | z: 3, 7 | // A generator that yields each of the keys of this object 8 | *g() { 9 | for (let key of Object.keys(this)) { 10 | yield key; 11 | } 12 | }, 13 | }; 14 | [...o.g()]; // => ["x", "y", "z", "g"] 15 | -------------------------------------------------------------------------------- /12-Iterators&Generators/app6.js: -------------------------------------------------------------------------------- 1 | // 🌟 Generator Examples 2 | 3 | // ⛔️ If this generator is used with the ... spread operator, 4 | // it will loop until memory is exhausted and the program crashes. 5 | 6 | function* fibonacciSequence() { 7 | let x = 0, 8 | y = 1; 9 | for (;;) { 10 | yield y; 11 | [x, y] = [y, x + y]; // Note: destructuring assignment 12 | console.log(`✨ ${x}`); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /12-Iterators&Generators/app7.js: -------------------------------------------------------------------------------- 1 | // 🌟 Generator Examples 2 | 3 | function* fibonacciSequence() { 4 | let x = 0, 5 | y = 1; 6 | for (;;) { 7 | yield y; 8 | [x, y] = [y, x + y]; // Note: destructuring assignment 9 | } 10 | } 11 | 12 | // 🌟 다음과 같이 Break 조건을 추가하여 특정 n-th 피보나치 수를 구할 수 있음 13 | // Return the nth Fibonacci number 14 | 15 | function fibonacci(n) { 16 | for (let f of fibonacciSequence()) { 17 | if (n-- <= 0) return f; 18 | } 19 | } 20 | fibonacci(20); // => 10946 21 | -------------------------------------------------------------------------------- /12-Iterators&Generators/app8.js: -------------------------------------------------------------------------------- 1 | // 🌟 Generator Examples 2 | 3 | function* fibonacciSequence() { 4 | let x = 0, 5 | y = 1; 6 | for (;;) { 7 | yield y; 8 | [x, y] = [y, x + y]; // Note: destructuring assignment 9 | } 10 | } 11 | 12 | // 🌟 ① n-th 까지 피보나치 수를 얻는 방법 13 | // Yield the first n elements of the specified iterable object 14 | function* take(n, iterable) { 15 | let it = iterable[Symbol.iterator](); // Get iterator for iterable object 16 | while (n-- > 0) { 17 | // Loop n times: 18 | let next = it.next(); // Get the next item from the iterator. 19 | if (next.done) return; // If there are no more values, return early 20 | else yield next.value; // otherwise, yield the value 21 | } 22 | } 23 | // An array of the first 5 Fibonacci numbers 24 | console.log("①", [...take(5, fibonacciSequence())]); // => [1, 1, 2, 3, 5] 25 | 26 | // 🌟 ② iterator를 생성할 필요없이 다음과 같이 할 수 있음 27 | // Yield the first n elements of the specified iterable object 28 | function* take(n, iterable) { 29 | while (n-- > 0) { 30 | // Loop n times: 31 | let next = iterable.next(); // Get the next item from the iterator. 32 | if (next.done) return; // If there are no more values, return early 33 | else yield next.value; // otherwise, yield the value 34 | } 35 | } 36 | // An array of the first 5 Fibonacci numbers 37 | console.log("②", [...take(5, fibonacciSequence())]); // => [1, 1, 2, 3, 5] 38 | -------------------------------------------------------------------------------- /12-Iterators&Generators/app9.js: -------------------------------------------------------------------------------- 1 | // 🌟 Generator Examples 2 | 3 | // A generator function that yields the set of one digit (base-10) primes. 4 | function* oneDigitPrimes() { 5 | // Invoking this function does not run the code 6 | yield 2; // but just returns a generator object. Calling 7 | yield 3; // the next() method of that generator runs 8 | yield 5; // the code until a yield statement provides 9 | yield 7; // the return value for the next() method. 10 | } 11 | 12 | // Given an array of iterables, yield their elements in interleaved order. 13 | function* zip(...iterables) { 14 | // Get an iterator for each iterable 15 | let iterators = iterables.map((i) => i[Symbol.iterator]()); 16 | let index = 0; 17 | while (iterators.length > 0) { 18 | // While there are still some iterators 19 | while (iterators.length > 0) { 20 | // While there are still some iterators 21 | if (index >= iterators.length) { 22 | // If we reached the last iterator 23 | index = 0; // go back to the first one. 24 | } 25 | let item = iterators[index].next(); // Get next item from next iterator. 26 | if (item.done) { 27 | // If that iterator is done 28 | iterators.splice(index, 1); // then remove it from the array. 29 | } else { 30 | // Otherwise, 31 | yield item.value; // yield the iterated value 32 | index++; // and move on to the next iterator. 33 | } 34 | } 35 | } 36 | } 37 | 38 | // Interleave three iterable objects 39 | [...zip(oneDigitPrimes(), "ab", [0])]; // => [2,"a",0,3,"b",5,7] 40 | -------------------------------------------------------------------------------- /12-Iterators&Generators/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ✨✨ Chapter 12. Iterators and Generators 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /13-AsynchronousJS/1-1/app1.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.1.1 Timers 2 | 3 | const checkForUpdates = function (x) { 4 | console.log(x); 5 | }; 6 | setTimeout(() => { 7 | console.log(`💕💕💕💕`); 8 | }, 3000); 9 | 10 | setTimeout(() => { 11 | checkForUpdates(`🤣`); 12 | }, 5000); 13 | 14 | // Call checkForUpdates in one minute and then again every minute after that 15 | let updateIntervalId = setInterval(() => { 16 | checkForUpdates(`💕`); 17 | }, 7000); 18 | 19 | setTimeout(stopCheckingForUpdates, 30000); 20 | 21 | // setInterval() returns a value that we can use to stop the repeated 22 | // invocations by calling clearInterval(). (Similarly, setTimeout() 23 | // returns a value that you can pass to clearTimeout()) 24 | function stopCheckingForUpdates() { 25 | clearInterval(updateIntervalId); 26 | console.log(`🔥`); 27 | } 28 | -------------------------------------------------------------------------------- /13-AsynchronousJS/1-1/app2.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.1.1 Timers 2 | 3 | "use strict"; 4 | 5 | const start = new Date(); 6 | let i = 0; 7 | const intervalId = setInterval(() => { 8 | let now = new Date(); 9 | if (now.getMinutes() !== start.getMinutes() || ++i > 10) 10 | return clearInterval(intervalId); 11 | console.log(`${i}: ${now}`); 12 | }, 5 * 1000); 13 | 14 | // const start = new Date(); 15 | // let i = 0; 16 | // const intervalId = setInterval(function () { 17 | // let now = new Date(); 18 | // if (now.getMinutes() !== start.getMinutes() || ++i > 10) 19 | // return clearInterval(intervalId); 20 | // console.log(`${i}: ${now}`); 21 | // }, 5 * 1000); 22 | -------------------------------------------------------------------------------- /13-AsynchronousJS/1-1/app3.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.1.1 Timers 2 | 3 | "use strict"; 4 | console.log("Before timeout: " + new Date()); 5 | function f() { 6 | console.log("After timeout: " + new Date()); 7 | 200; 8 | } 9 | setTimeout(f, 60 * 1000); // one minute 10 | console.log("I happen after setTimeout!"); 11 | console.log("Me too!"); 12 | 13 | // using arrow function 14 | console.log("Before timeout: " + new Date()); 15 | setTimeout(() => { 16 | console.log("After timeout: " + new Date()); 17 | }, 60 * 1000); 18 | 19 | console.log("I happen after setTimeout!"); 20 | console.log("Me too!"); 21 | -------------------------------------------------------------------------------- /13-AsynchronousJS/1-1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ✨✨ Chapter 13. Asynchronous JS 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /13-AsynchronousJS/1-2/Dweb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dweb-Incheon/JS/9a06f1954fc98bf813480101f372a91b6d81d660/13-AsynchronousJS/1-2/Dweb.png -------------------------------------------------------------------------------- /13-AsynchronousJS/1-2/INU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dweb-Incheon/JS/9a06f1954fc98bf813480101f372a91b6d81d660/13-AsynchronousJS/1-2/INU.png -------------------------------------------------------------------------------- /13-AsynchronousJS/1-2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ✨✨ Chapter 13. Asynchronous JS 7 | 8 | 9 |
10 | 11 |
12 |
13 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /13-AsynchronousJS/1-3/app.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.1.3 Network Events 2 | let obj; 3 | 4 | function getCurrentVersionNumber() { 5 | // Turn on "json-server" 6 | let request = new XMLHttpRequest(); 7 | request.open("GET", "http://localhost:3000/web"); 8 | request.send(); 9 | // Register a callback that will be invoked when the response arrives 10 | request.onload = () => { 11 | if (request.status === 200) { 12 | // If HTTP status is good, get version number and call callback. 13 | console.log(request.response); 14 | const obj = JSON.parse(request.response); // string -> JSON object 15 | console.log(`💕`, obj); 16 | const btnElement = document.getElementById("demo"); 17 | btnElement.innerText = obj[0].name; 18 | } else { 19 | console.error(`🚨`); // Otherwise report an error to the callback 20 | } 21 | }; 22 | // Register another callback that will be invoked for network errors 23 | request.onerror = request.ontimeout = function (e) { 24 | console.log(`⛔️`, e); 25 | }; 26 | 27 | console.log(`😃 내가 먼저 실행되지롱~`); 28 | console.log(`🙋 나도 나도 실행되지롱~`); 29 | console.log(`😊 나도 나도`); 30 | } 31 | -------------------------------------------------------------------------------- /13-AsynchronousJS/1-3/db.json: -------------------------------------------------------------------------------- 1 | { 2 | "web": [ 3 | { 4 | "id": 1, 5 | "studentID": "20201234", 6 | "name": "Kim" 7 | }, 8 | { 9 | "studentID": "12344332", 10 | "name": "james", 11 | "id": 2 12 | } 13 | ], 14 | "server": [ 15 | { 16 | "id": 1, 17 | "studentID": "20212323", 18 | "name": "Lee" 19 | } 20 | ], 21 | "blockchain": [ 22 | { 23 | "studentID": "202503021", 24 | "name": "Lee", 25 | "id": 1 26 | }, 27 | { 28 | "gender": "female", 29 | "id": 2 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /13-AsynchronousJS/1-3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ✨✨ Chapter 13. Asynchronous JS 7 | 8 | 9 |

13.1.3 Network Events

10 | 11 |
12 | 15 |
16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /13-AsynchronousJS/1-4/app1.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.1.4 Callbacks and Events in Node 2 | 3 | // The "fs" module has filesystem-related APIs 4 | 5 | const fs = require("fs"); 6 | 7 | let options = { 8 | // An object to hold options for our program 9 | // default options would go here 10 | }; 11 | // Read a configuration file, then call the callback function 12 | // ⛔️ 경로 주의: 해당 디렉토리에서 실행할 것 13 | fs.readFile("./config.json", "utf-8", (err, text) => { 14 | if (err) { 15 | // If there was an error, display a warning, but continue 16 | console.warn("Could not read config file:", err); 17 | } else { 18 | // Otherwise, parse the file contents and assign to the options object 19 | Object.assign(options, JSON.parse(text)); 20 | } 21 | // In either case, we can now start running the program 22 | startProgram(options); 23 | }); 24 | console.log(`😯`, options); 25 | 26 | function startProgram(options) { 27 | console.log(`💕`, options); 28 | } 29 | -------------------------------------------------------------------------------- /13-AsynchronousJS/1-4/app2.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.1.4 Callbacks and Events in Node 2 | 3 | const https = require("https"); 4 | 5 | getText("https://giseok.watchdognet.com", (status, body) => { 6 | console.log(`statud code ${status}`); 7 | console.log(`body ${body}`); 8 | }); 9 | console.log(`💕💕💕💕💕`); 10 | 11 | // Read the text content of the URL and asynchronously pass it to the callback. 12 | function getText(url, callback) { 13 | // Start an HTTP GET request for the URL 14 | https.get(url, (res) => { 15 | let httpStatus = res.statusCode; 16 | let body = ""; // which we will accumulate here. 17 | res.on(`data`, (chunk) => { 18 | body += chunk; 19 | }); 20 | res.on(`end`, () => { 21 | if (httpStatus === 200) { 22 | // If the HTTP response was good 23 | callback(null, body); // Pass response body to the callback 24 | } else { 25 | // Otherwise pass an error 26 | callback(httpStatus, null); 27 | } 28 | }); 29 | res.on(`error`, (err) => { 30 | callback(err, null); 31 | }); 32 | }); 33 | } 34 | -------------------------------------------------------------------------------- /13-AsynchronousJS/1-4/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "web": [ 3 | { "name": "choi", "id": 12345678 }, 4 | { "name": "kim", "id": 12345678 } 5 | ], 6 | "server": [ 7 | { "name": "lee", "id": 12345678 }, 8 | { "name": "ko", "id": 12345678 } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /13-AsynchronousJS/1-5/app1.js: -------------------------------------------------------------------------------- 1 | // 🌟 Scope (Closure) and Asynchronous Execution 2 | 3 | function countdown() { 4 | console.log("countdown:"); 5 | for (let i = 5; i >= 0; i--) { 6 | setTimeout(function () { 7 | console.log(i == 0 ? "Go!" : i); 8 | }, (5 - i) * 1000); 9 | } 10 | } 11 | countdown(); 12 | -------------------------------------------------------------------------------- /13-AsynchronousJS/1-5/app2.js: -------------------------------------------------------------------------------- 1 | // 🌟 Error-First Callbacks 2 | 3 | const fs = require("fs"); 4 | const fname = `may_or_may_not_exist.txt`; 5 | //const fname = `incheon.txt`; 6 | 7 | fs.readFile(fname, function (err, data) { 8 | if (err) return console.error(`error reading file ${fname}: ${err.massage}`); 9 | console.log(`${fname} contents: ${data}`); 10 | }); 11 | -------------------------------------------------------------------------------- /13-AsynchronousJS/1-5/incheon.txt: -------------------------------------------------------------------------------- 1 | Incheon National University 😘 -------------------------------------------------------------------------------- /13-AsynchronousJS/1-6/a.txt: -------------------------------------------------------------------------------- 1 | Incheon National University -------------------------------------------------------------------------------- /13-AsynchronousJS/1-6/app1.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | 3 | fs.readFile("./a.txt", (err, dataA) => { 4 | if (err) console.error(err); 5 | fs.readFile("./b.txt", (err, dataB) => { 6 | if (err) console.error(err); 7 | fs.readFile("./c.txt", (err, dataC) => { 8 | if (err) console.error(err); 9 | setTimeout(() => { 10 | fs.writeFile("./d.txt", dataA + dataB + dataC, (err) => { 11 | if (err) console.error(err); 12 | }); 13 | }, 30 * 1000); 14 | }); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /13-AsynchronousJS/1-6/app2.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | 3 | fs.readFile("./a.txt", (err, dataA) => { 4 | if (err) console.error(err); 5 | fs.readFile("./b.txt", (err, dataB) => { 6 | if (err) console.error(err); 7 | try { 8 | fs.readFile("./c.txt", (err, dataC) => { 9 | if (err) throw err; 10 | setTimeout(() => { 11 | fs.writeFile("./d.txt", dataA + dataB + dataC, (err) => { 12 | if (err) console.error(err); 13 | }); 14 | }, 30 * 1000); 15 | }); 16 | } catch (err) { 17 | console.error(`🚨`); 18 | console.error(err); 19 | } 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /13-AsynchronousJS/1-6/b.txt: -------------------------------------------------------------------------------- 1 | 2 | Dept. of Computer Science and Engineering -------------------------------------------------------------------------------- /13-AsynchronousJS/2-1/app1.js: -------------------------------------------------------------------------------- 1 | $.getJSON("http://localhost:3000/web").then((jsonData) => { 2 | console.log(jsonData); 3 | // This is a callback function that will be asynchronously 4 | // invoked with the parsed JSON value when it becomes available. 5 | }); 6 | 7 | // Suppose you have a function like this to display a user profile 8 | 9 | //function displayUserProfile(profile) { 10 | /* implementation omitted */ 11 | //} 12 | // Here's how you might use that function with a Promise. 13 | // Notice how this line of code reads almost like an English sentence: getJSON("/api/user/profile").then(displayUserProfile); 14 | //getJSON("/api/user/profile").then(displayUserProfile, handleProfileError); 15 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-1/app2.js: -------------------------------------------------------------------------------- 1 | $.getJSON("http://localhost:3000/web111111") 2 | .then((jsonData) => { 3 | console.log(jsonData); 4 | }) 5 | .catch((error) => { 6 | console.log("⛔️", error); 7 | }); 8 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-1/db.json: -------------------------------------------------------------------------------- 1 | { 2 | "web": [ 3 | { 4 | "id": 1, 5 | "studentID": "20201234", 6 | "name": "Kim" 7 | } 8 | ], 9 | "linux": [ 10 | { 11 | "id": 1, 12 | "studentID": "20212323", 13 | "name": "Lee" 14 | } 15 | ], 16 | "blockchain": [ 17 | { 18 | "studentID": "202503021", 19 | "name": "Lee", 20 | "id": 1 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ✨✨ Chapter 13. Asynchronous JS 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-2/app1.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.2.2 Chaining Promises 2 | 3 | fetch("http://localhost:3000/web").then((response) => { 4 | // When the promise resolves, we have status and headers 5 | if (response.ok) { 6 | console.log(response); // What can we do here? We don't actually have the response body yet. 7 | } 8 | }); 9 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-2/app2.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.2.2 Chaining Promises 2 | 3 | // Naive way to get a body of response obhect 4 | fetch("http://localhost:3000/web").then((response) => { 5 | response.json().then((profile) => { 6 | // Ask for the JSON-parsed body 7 | // When the body of the response arrives, it will be automatically parsed as JSON and passed to this function. 8 | displayUserProfile(profile); 9 | }); 10 | }); 11 | 12 | function displayUserProfile(body) { 13 | console.log(body); 14 | } 15 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-2/app3.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.2.2 Chaining Promises 2 | 3 | // 🌟 method chain: fetch().then().then() ✨ 4 | // 😀 The preferred idiom to use Promises in a sequential chain 5 | 6 | let p = fetch("http://localhost:3000/web") 7 | .then((response) => { 8 | return response.json(); 9 | }) 10 | .then((profile) => { 11 | displayUserProfile(profile); 12 | }); 13 | 14 | console.log(p); 15 | 16 | setTimeout(() => { 17 | console.log(p); 18 | }, 5000); 19 | 20 | function displayUserProfile(body) { 21 | console.log(body); 22 | } 23 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-2/app4.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.2.2 Chaining Promises 2 | // 🌟 Summary ✨ 3 | 4 | fetch(theURL) // task 1; returns promise 1 5 | .then(callback1) // task 2; returns promise 2 6 | .then(callback2); // task 3; returns promise 3 7 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-2/app5.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.2.2 Chaining Promises 2 | // Ex. hypothetical Promise chain 3 | fetch("http://localhost:3000/web") // Make an HTTP request 4 | .then((response) => response.json()) // Ask for the JSON body of the response 5 | .then((document) => { 6 | // When we get the parsed JSON 7 | return render(document); // display the document to the user 8 | }) 9 | .then((rendered) => { 10 | // When we get the rendered document 11 | console.log(`🔥 ${rendered}`); 12 | //cacheInDatabase(rendered); // cache it in the local database. 13 | }) 14 | .catch((error) => handle(error)); // Handle any errors that occur 15 | 16 | // ✨ callbacks 정의 17 | function render(items) { 18 | const contatiner = document.querySelector("#dweb"); 19 | contatiner.innerHTML = items.map((item) => createHTMLString(item)).join(""); 20 | return contatiner.innerHTML; 21 | } 22 | 23 | function createHTMLString(item) { 24 | return `
  • ${item.studentID} : ${item.name}
  • `; 25 | } 26 | 27 | function handle(e) { 28 | console.log("Catch Block"); 29 | alert(`Error happens: ${e.name}: ${e.message}`); 30 | } 31 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-2/db.json: -------------------------------------------------------------------------------- 1 | { 2 | "web": [ 3 | { 4 | "id": 1, 5 | "studentID": "20201234", 6 | "name": "Kim" 7 | }, 8 | { 9 | "id": 2, 10 | "studentID": "20181234", 11 | "name": "Choi" 12 | } 13 | ], 14 | "linux": [ 15 | { 16 | "id": 1, 17 | "studentID": "20212323", 18 | "name": "Lee" 19 | } 20 | ], 21 | "blockchain": [ 22 | { 23 | "studentID": "202503021", 24 | "name": "Lee", 25 | "id": 1 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ✨✨ Chapter 13. Asynchronous JS 7 | 8 | 9 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-3/app1.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.2.3 Resolving Promises 2 | 3 | function c1(response) { 4 | console.log(`✨p1:`, p1); // fullfilled 5 | let p = response.json(); 6 | console.log(`✨p returned by json:`, p); // pending 7 | return p; // returns promise! 8 | } 9 | 10 | function c2(profile) { 11 | console.log(profile); 12 | // return new Promise((resolve, reject) => { 13 | // resolve(new Error("Time travel not yet implemented")); 14 | // }); 15 | } 16 | 17 | let p1 = fetch("http://localhost:3000/web"); // promise 1, task 1 18 | let p2 = p1.then(c1); // promise 2, task 2 19 | let p3 = p2.then(c2); // promise 3, task 3 20 | 21 | console.log(`p1:`, p1); // pending 22 | console.log(`p2:`, p2); // 🌟 Remember if callback returns a promise, that promise would be a pending(resolve) state. 23 | console.log(`p3:`, p3); // pending 24 | 25 | setTimeout(() => { 26 | console.log(`⛔️p1:`, p1, `⛔️p2:`, p2, `⛔️p3:`, p3); // fulfill 27 | }, 5000); 28 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-3/db.json: -------------------------------------------------------------------------------- 1 | { 2 | "web": [ 3 | { 4 | "id": 1, 5 | "studentID": "20201234", 6 | "name": "Kim" 7 | }, 8 | { 9 | "id": 2, 10 | "studentID": "20181234", 11 | "name": "Choi" 12 | } 13 | ], 14 | "linux": [ 15 | { 16 | "id": 1, 17 | "studentID": "20212323", 18 | "name": "Lee" 19 | } 20 | ], 21 | "blockchain": [ 22 | { 23 | "studentID": "202503021", 24 | "name": "Lee", 25 | "id": 1 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-3/flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dweb-Incheon/JS/9a06f1954fc98bf813480101f372a91b6d81d660/13-AsynchronousJS/2-3/flow.png -------------------------------------------------------------------------------- /13-AsynchronousJS/2-3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ✨✨ Chapter 13. Asynchronous JS 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-4/app1.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.2.4 More on Promises and Errors 2 | 3 | // 😀 .catch() := .then() with null as the first argument and an error-handling callback as the second argument 4 | 5 | p = fetch("http://xxx:3000/web"); // It'll throw an error 6 | 7 | // lines 4 and 5 are exactly the same 8 | p.then(null, cb); 9 | p.catch(cb); 10 | 11 | function cb(response) { 12 | console.log("🔥"); 13 | console.error(response); 14 | } 15 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-4/app2.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.2.4 More on Promises and Errors 2 | 3 | // 🌟 .finally() 4 | // 😀 the callback you pass to .finally() will be certainly invoked when the Promise you called it on settles. 5 | 6 | fetch("https://api/user/profile") // It'll throw an error 7 | .then((res) => { 8 | console.log(`😀`); 9 | }) 10 | .catch((res) => { 11 | console.log(`😅`); 12 | }) 13 | .finally(() => { 14 | console.log(`😇`); 15 | }); 16 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-4/app3.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.2.4 More on Promises and Errors 2 | 3 | // 😃 resolve: https://jsonplaceholder.typicode.com/posts 4 | // 🤬 reject (throw error): https://api/user/profile 5 | 6 | fetch("https://api/user/profile") // Start the HTTP request 7 | .then((response) => { 8 | // Call this when status and headers are ready 9 | 10 | if (!response.ok) { 11 | // If we got a 404 Not Found or similar error 12 | // 🌟 response.ok 의 status code가 200 과 같은 정상 결과가 아닌 경우 null 반환 13 | return null; // Maybe user is logged out; return null profile 14 | } 15 | // Now check the headers to ensure that the server sent us JSON. 16 | // If not, our server is broken, and this is a serious error! 17 | let type = response.headers.get("content-type"); 18 | if (type !== "application/json; charset=utf-8") { 19 | throw new TypeError(`Expected JSON, got ${type}`); 20 | } 21 | // If we get here, then we got a 2xx status and a JSON content-type 22 | // so we can confidently return a Promise for the response 23 | // body as a JSON object. 24 | return response.json(); 25 | }) 26 | .then((profile) => { 27 | // Called with the parsed response body or null 28 | if (profile) { 29 | displayUserProfile(profile); 30 | } else { 31 | // If we got a 404 error above and returned null we end up here 32 | displayLoggedOutProfilePage(); 33 | } 34 | }) 35 | .catch((e) => { 36 | if (e instanceof NetworkError) { 37 | // fetch() can fail this way if the internet connection is down 38 | displayErrorMessage("Check your internet connection."); 39 | } else if (e instanceof TypeError) { 40 | // This happens if we throw TypeError above 41 | displayErrorMessage("Something is wrong with our server!"); 42 | } else { 43 | // This must be some kind of unanticipated error 44 | console.error(e); 45 | } 46 | }) 47 | .finally(() => { 48 | console.log(`🙌 Terminate Program`); 49 | }); 50 | 51 | class NetworkError {} 52 | function displayUserProfile(profile) { 53 | console.log(`😀 Resolve`); 54 | } 55 | function displayLoggedOutProfilePage() {} 56 | function displayLoggedOutProfilePage() {} 57 | function displayErrorMessage(msg) { 58 | console.log(msg); 59 | } 60 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-4/app4.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.2.4 More on Promises and Errors 2 | 3 | // 💿 Use case. Database Query 4 | // 😀 네트워크 혼잡을 고려하여 500ms 마다 쿼리 수행 5 | queryDatabase() 6 | .catch((e) => wait(500).then(queryDatabase)) // On failure, wait and retry 7 | .then(displayTable) 8 | .catch(displayDatabaseError); 9 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-4/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ✨✨ Chapter 13. Asynchronous JS 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-5/app1.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.2.5 Promises in Parallel 2 | 3 | // 🌟 Promise.all() 4 | 5 | async function getJSON(url) { 6 | let response = await fetch(url); 7 | let body = await response.json(); 8 | console.log(url); 9 | return body; 10 | } 11 | 12 | // 🌟 getJSON 함수가 순차적으로 수행됨 13 | let P = Promise.all([ 14 | getJSON("https://jsonplaceholder.typicode.com/posts"), 15 | getJSON("https://jsonplaceholder.typicode.com/comments"), 16 | // 주석을 풀면 Rejected 17 | // getJSON("https://api/user/profile") 18 | ]); 19 | P.then((res) => { 20 | console.log(P); 21 | console.log(res[0]); 22 | console.log(res[1]); 23 | }).catch((e) => { 24 | // 😀 하나라도 Reject 되는 경우 에러 반환 25 | console.log(P); 26 | console.log(e); 27 | }); 28 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-5/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ✨✨ Chapter 13. Asynchronous JS 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-6/app1.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.2.6 Making Promises - Promises based on other Promises 2 | 3 | // 🌟 Promise를 만드는 첫 번째 방법: Promise를 반환하는 함수를 이용하자 4 | // 🤔 Promise를 만드는 getJSON() 함수를 만들어보자 5 | // 😃 Resolve. "https://jsonplaceholder.typicode.com/posts" 6 | // 😡 Reject. "https://api/user/profile" 7 | 8 | function getJSON(url) { 9 | return fetch(url).then((response) => response.json()); 10 | } 11 | 12 | function getHighScore() { 13 | return getJSON("http://localhost:3000/web").then((profile) => { 14 | for (let i in profile) console.log(`💕`, profile[i].studentID); 15 | }); 16 | } 17 | 18 | getHighScore(); 19 | console.log(`🌟 getJSON, getHighScore도 이제 비동기 함수들입니다.`); 20 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-6/app2.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.2.6 Making Promises - Promises from scratch 2 | // 🌟 Promise를 만드는 두 번째 방법: "Promise.resolve()" 와 "Promise.reject()" 활용 3 | 4 | function wait(duration) { 5 | // Create and return a new Promise 6 | return new Promise((resolve, reject) => { 7 | if (duration < 0) { 8 | reject(new Error("Time travel not yet implemented")); 9 | } 10 | setTimeout(() => { 11 | resolve(fetch("http://localhost:3000/web")); 12 | }, duration); 13 | }); 14 | } 15 | 16 | wait(-2000) 17 | .then(() => { 18 | console.log(`🐥`); 19 | }) 20 | .catch((e) => { 21 | console.log(e); 22 | }) 23 | .finally(() => { 24 | alert(`🤔 👍`); 25 | }); 26 | 27 | console.log(p); 28 | 29 | setTimeout(() => { 30 | console.log(p); 31 | }, 5000); 32 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-6/app3.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.2.6 Making Promises - Promises from scratch 2 | 3 | // 🌟 Promise를 만드는 두 번째 방법: "Promise.resolve()" 와 "Promise.reject()" 활용 4 | 5 | function wait(duration) { 6 | // Create and return a new Promise 7 | return new Promise((resolve, reject) => { 8 | setTimeout(() => { 9 | resolve(511); 10 | }, duration); 11 | }); 12 | } 13 | 14 | let p = wait(3000); 15 | 16 | setTimeout(() => { 17 | console.log(p); 18 | }, 1); 19 | setTimeout(() => { 20 | console.log(p); 21 | }, 5000); 22 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-6/app4.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.2.6 Making Promises - Promises from scratch 2 | // 🌟 Promise를 만드는 두 번째 방법: "Promise.resolve()" 와 "Promise.reject()" 활용 3 | 4 | function wait(duration) { 5 | // Create and return a new Promise 6 | return new Promise((resolve, reject) => { 7 | // If the argument is invalid, reject the Promise 8 | if (duration < 0) { 9 | setTimeout(() => { 10 | reject(new Error("Time travel not yet implemented")); 11 | }, 1000); 12 | } 13 | // Otherwise, wait asynchronously and then resolve the Promise. 14 | // setTimeout will invoke resolve() with no arguments, which means 15 | // that the Promise will fulfill with the undefined value. 16 | else 17 | setTimeout(() => { 18 | resolve(fetch("http://localhost:3000/web")); 19 | }, duration); 20 | }); 21 | } 22 | 23 | let p = wait(1000); 24 | 25 | p.then((response) => { 26 | return response.text(); 27 | }) 28 | .then((profile) => { 29 | console.log(`✨`, profile); 30 | }) 31 | .catch((e) => { 32 | console.error(e); 33 | }); 34 | 35 | console.log(p); 36 | 37 | setTimeout(() => { 38 | console.log(p); 39 | }, 5000); 40 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-6/app5.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.2.6 Making Promises - Promises from scratch 2 | 3 | // 🌟 Making a Promise in Node Environment 4 | // 🌟 In this example, we're not going to use Fetch() API. 5 | // 😃 Resolve. "https://jsonplaceholder.typicode.com/posts" 6 | // 😡 Reject. "https://api/user/profile" 7 | 8 | import https from "https"; 9 | 10 | getJSON("https://jsonplaceholder.typicode.com/posts").then((profile) => { 11 | console.log(`✨`, profile); 12 | }); 13 | 14 | function getJSON(url) { 15 | return new Promise((resolve, reject) => { 16 | const request = https.get(url, (response) => { 17 | if (response.statusCode !== 200) { 18 | reject(new Error(`HTTP Status ${response.statusCode}`)); 19 | response.resume(); // so we don't leak memory 20 | } else if ( 21 | response.headers["content-type"] !== "application/json; charset=utf-8" 22 | ) { 23 | reject(new Error("Invalid content-type")); 24 | response.resume(); 25 | } else { 26 | // Otherwise, register events to read the body of the response 27 | let body = ""; 28 | response.setEncoding("utf-8"); 29 | response.on("data", (chunk) => { 30 | body += chunk; 31 | }); 32 | response.on("end", () => { 33 | // When the response body is complete, try to parse it 34 | try { 35 | let parsed = JSON.parse(body); 36 | // If it parsed successfully, fulfill the promise 37 | resolve(parsed); 38 | } catch (e) { 39 | // If parsing failed, reject the Promise 40 | reject(e); 41 | } 42 | }); 43 | } 44 | }); 45 | // We also reject the Promise if the request fails before we 46 | // even get a response (such as when the network is down) 47 | request.on("error", (error) => { 48 | reject(error); 49 | }); 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-6/db.json: -------------------------------------------------------------------------------- 1 | { 2 | "web": [ 3 | { 4 | "id": 1, 5 | "studentID": "20201234", 6 | "name": "Kim" 7 | }, 8 | { 9 | "id": 2, 10 | "studentID": "20181234", 11 | "name": "Choi" 12 | } 13 | ], 14 | "linux": [ 15 | { 16 | "id": 1, 17 | "studentID": "20212323", 18 | "name": "Lee" 19 | } 20 | ], 21 | "blockchain": [ 22 | { 23 | "studentID": "202503021", 24 | "name": "Lee", 25 | "id": 1 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /13-AsynchronousJS/2-6/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ✨✨ Chapter 13. Asynchronous JS 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /13-AsynchronousJS/3-1/app1.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.3.1 await Expressions 2 | 3 | let response = await fetch("https://jsonplaceholder.typicode.com/posts"); 4 | let profile = response.json(); 5 | 6 | console.log(response); 7 | console.log(profile); 8 | -------------------------------------------------------------------------------- /13-AsynchronousJS/3-1/app2.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.3.2 async Functions 2 | 3 | async function getHighScore() { 4 | let response = await fetch("https://jsonplaceholder.typicode.com/posts"); 5 | let profile = await response.json(); 6 | console.log(`💕`); 7 | return profile.highScore; 8 | } 9 | 10 | let s = getHighScore(); 11 | console.log(s); 12 | console.log(`⏰`); 13 | 14 | setTimeout(() => { 15 | console.log(s); 16 | }, 3000); 17 | -------------------------------------------------------------------------------- /13-AsynchronousJS/3-1/app3.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.3.3 Awaiting Multiple Promises 2 | 3 | // ✨ await → 프로미스를 반환하는 함수에 사용됨. 여전히 비동기 코드라는 것을 염두할 것 4 | // ✨ 따라서, "async" 와 함께 쓰여야 함 5 | // ✨ "You can only use the await keyword within functions 6 | // that have been declared with the async keyword" 7 | 8 | async function getJSON() { 9 | let response = await fetch("https://jsonplaceholder.typicode.com/posts"); 10 | let profile = await response.json(); 11 | console.log(`😀`); // getJSON 함수 안에서는 동기적으로 수행됨 12 | return profile[0]; 13 | } 14 | console.log(`😡`); 15 | getJSON().then((res) => { 16 | console.log(`💕`, res); 17 | }); 18 | console.log(`🤬`); // 😡 -> 🤬 -> 😀 순서로 출력 19 | -------------------------------------------------------------------------------- /13-AsynchronousJS/3-1/app4.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.3.2 async Functions 2 | 3 | displayHighScore(await getHighScore()); 4 | console.log(`🐱`); 5 | 6 | getHighScore().then(displayHighScore).catch(console.error); 7 | console.log(`🐹`); 8 | 9 | async function getHighScore() { 10 | let response = await fetch("https://jsonplaceholder.typicode.com/posts"); 11 | let profile = await response.json(); 12 | console.log(`💕`); 13 | return profile; 14 | } 15 | 16 | function displayHighScore(xxx) { 17 | console.log(xxx); 18 | } 19 | -------------------------------------------------------------------------------- /13-AsynchronousJS/3-1/app5.js: -------------------------------------------------------------------------------- 1 | // 🌟 13.3.3 Awaiting Multiple Promises 2 | 3 | async function getJSON(url) { 4 | let response = await fetch(url); 5 | let body = await response.json(); 6 | if (url === "http://localhost:3000/web") console.log(`🙋`); 7 | else console.log(`😘`); 8 | return body; 9 | } 10 | 11 | let [value1, value2] = await Promise.all([ 12 | getJSON("http://localhost:3000/web"), 13 | getJSON("http://localhost:3000/linux"), 14 | ]); 15 | 16 | // let value1 = await getJSON("http://localhost:3000/web"); 17 | // let value2 = await getJSON("http://localhost:3000/linux"); 18 | -------------------------------------------------------------------------------- /13-AsynchronousJS/3-1/db.json: -------------------------------------------------------------------------------- 1 | { 2 | "web": [ 3 | { 4 | "id": 1, 5 | "studentID": "20201234", 6 | "name": "Kim" 7 | }, 8 | { 9 | "id": 2, 10 | "studentID": "20181234", 11 | "name": "Choi" 12 | }, 13 | { 14 | "id": 1, 15 | "studentID": "20201234", 16 | "name": "Kim" 17 | }, 18 | { 19 | "id": 2, 20 | "studentID": "20181234", 21 | "name": "Choi" 22 | }, 23 | { 24 | "id": 1, 25 | "studentID": "20201234", 26 | "name": "Kim" 27 | }, 28 | { 29 | "id": 2, 30 | "studentID": "20181234", 31 | "name": "Choi" 32 | }, 33 | { 34 | "id": 1, 35 | "studentID": "20201234", 36 | "name": "Kim" 37 | }, 38 | { 39 | "id": 2, 40 | "studentID": "20181234", 41 | "name": "Choi" 42 | }, 43 | { 44 | "id": 1, 45 | "studentID": "20201234", 46 | "name": "Kim" 47 | }, 48 | { 49 | "id": 2, 50 | "studentID": "20181234", 51 | "name": "Choi" 52 | } 53 | ], 54 | "linux": [ 55 | { 56 | "id": 1, 57 | "studentID": "20212323", 58 | "name": "Lee" 59 | } 60 | ], 61 | "blockchain": [ 62 | { 63 | "studentID": "202503021", 64 | "name": "Lee", 65 | "id": 1 66 | } 67 | ] 68 | } 69 | -------------------------------------------------------------------------------- /13-AsynchronousJS/3-1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ✨✨ Chapter 13. Asynchronous JS 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /13-AsynchronousJS/ex-promises/events.js: -------------------------------------------------------------------------------- 1 | // 이벤트는 Node의 Built-in 기능. 웹 브라우저에서 동작시키고자 한다면, jQuery를 활용할 것 2 | // 구독(Subscribe)하고자 하는 이벤트를 누구나 리스닝할 수 있음 3 | "use strict"; 4 | import EventEmitter from "events"; 5 | 6 | // event를 만들 수 있는 EventEmitter를 상속하여 Countdown class를 만듦 7 | // countdown.emit("tick", i); 8 | 9 | class Countdown extends EventEmitter { 10 | constructor(seconds, superstitious) { 11 | super(); 12 | this.seconds = seconds; 13 | this.superstitious = !!superstitious; 14 | } 15 | go() { 16 | // this의 current value를 반드시 저장해야 함 17 | // this 변수는 콜백 내에서 계속 변함 18 | // countdown을 this로 바꿔볼 것 19 | const countdown = this; 20 | return new Promise((resolve, reject) => { 21 | for (let i = countdown.seconds; i >= 0; i--) { 22 | setTimeout(() => { 23 | if (countdown.superstitious && i === 13) 24 | return reject(new Error("DEFINITELY NOT COUNTING THAT")); 25 | countdown.emit("tick", i); 26 | if (i === 0) resolve(); 27 | }, (countdown.seconds - i) * 1000); 28 | } 29 | }); 30 | } 31 | } 32 | 33 | function launch() { 34 | return new Promise(function (resolve, reject) { 35 | console.log("Lift off!"); 36 | setTimeout(function () { 37 | resolve("In orbit!"); 38 | }, 2 * 1000); // a very fast rocket indeed 39 | }); 40 | } 41 | const c = new Countdown(13).on("tick", (i) => console.log(i + "...")); 42 | c.go() 43 | .then(launch) 44 | .then(function (msg) { 45 | console.log(msg); 46 | }) 47 | .catch(function (err) { 48 | console.error("Houston, we have a problem...."); 49 | }); 50 | -------------------------------------------------------------------------------- /13-AsynchronousJS/ex-promises/promise1.js: -------------------------------------------------------------------------------- 1 | // Creating Promises 2 | 3 | // countdown is going to return a promise 4 | // when countdown is up 5 | 6 | function countdown1(seconds) { 7 | // new Promise instance with a function that 8 | // has resolve (fulfill) and reject callbacks 9 | return new Promise((resolve, reject) => { 10 | for (let i = seconds; i >= 0; i--) { 11 | setTimeout(() => { 12 | if (i > 0) console.log(i + `...`); 13 | else resolve(console.log("GO")); 14 | }, (seconds - i) * 1000); 15 | } 16 | }); 17 | } 18 | 19 | function countdown2(seconds) { 20 | return new Promise(function (resolve, reject) { 21 | for (let i = seconds; i >= 0; i--) { 22 | setTimeout(function () { 23 | if (i > 0) console.log(`${i} ...`); 24 | else resolve(console.log("GO"), alert("GO")); 25 | }, (seconds - i) * 1000); 26 | } 27 | }); 28 | } 29 | 30 | countdown2(5); 31 | -------------------------------------------------------------------------------- /13-AsynchronousJS/ex-promises/promise2.js: -------------------------------------------------------------------------------- 1 | // Using Promises 2 | "use strict"; 3 | class Student { 4 | constructor(name, age) { 5 | this.name = name; 6 | this.age = age; 7 | } 8 | me() { 9 | return `My name is ${this.name}!`; 10 | } 11 | } 12 | 13 | function countdown(seconds) { 14 | return new Promise((resolve, reject) => { 15 | for (let i = seconds; i >= 0; i--) { 16 | setTimeout(() => { 17 | if (i == 13) reject(new Error("Definetly not counting that")); 18 | if (i > 0) console.log(`${i} ...`); 19 | else resolve(new Student("Dweb", 22)); 20 | }, (seconds - i) * 1000); 21 | } 22 | }); 23 | } 24 | 25 | // Return Promise 26 | // 프로미스는 fullfill에 대한 "then" handler 와 error에 대한 "catch" handler를 지원함 27 | // countdown(15)과 countdown(10)으로 실행시켜 볼 것 28 | // resolve or reject이 호출되어도 함수는 계속 실행됨 29 | // 단지, Promise의 상태만이 관리된다는 것을 알 수 있음 30 | countdown(15) 31 | .then(function (obj) { 32 | console.log(`countdown completed successfully + ${obj.me()}`); 33 | }) 34 | .catch(function (err) { 35 | console.log(`countdown experienced an error: " + ${err.message}`); 36 | }); 37 | -------------------------------------------------------------------------------- /13-AsynchronousJS/ex-promises/promise3.js: -------------------------------------------------------------------------------- 1 | new Promise((resolveOuter) => { 2 | resolveOuter( 3 | new Promise((resolveInner) => { 4 | setTimeout(resolveInner, 1000); 5 | }) 6 | ); 7 | }); 8 | const myPromise = new Promise((resolve, reject) => { 9 | setTimeout(() => { 10 | resolve("foo"); 11 | }, 300); 12 | }); 13 | 14 | myPromise 15 | .then((value) => `${value} and bar`) 16 | .then((value) => `${value} and bar again`) 17 | .then((value) => `${value} and again`) 18 | .then((value) => `${value} and again`) 19 | .then((value) => { 20 | console.log(value); 21 | }) 22 | .catch((err) => { 23 | console.error(err); 24 | }); 25 | -------------------------------------------------------------------------------- /15-WebBrowser/1-1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Digital Clock 8 | 20 | 21 | 22 | 23 |

    Digital Clock

    24 | 25 | 26 | 27 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /15-WebBrowser/11-1/app1.js: -------------------------------------------------------------------------------- 1 | // 🌟 fetch 함수 사용 예시 2 | // ✨ status property는 HTTP status code를 의미 3 | // - 200 : 요청에 성공한 것 4 | // - 404 : Not Found 5 | // ✨ 200이면, Response의 ok Property가 "true" 6 | 7 | fetch("http://localhost:3000/web") 8 | .then((response) => { 9 | if ( 10 | response.ok && 11 | response.headers.get("Content-Type") === "application/json; charset=utf-8" 12 | ) { 13 | // console.log(response.headers.has("Content-Type")); 14 | return response.json(); 15 | } else { 16 | throw new Error( 17 | `Unexpected response status ${response.status} or content type` 18 | ); 19 | } 20 | }) 21 | .then((profile) => { 22 | return displayUserInfo(profile); 23 | }) 24 | .then((res) => console.log(res)) 25 | .catch((error) => { 26 | console.log("Error while fetching current user:", error); 27 | }); 28 | 29 | // 📚 fetch 데이터를 IndexedDB에 저장할 것 30 | function displayUserInfo(data) { 31 | console.log(data); 32 | return `🌟 Completed`; 33 | } 34 | -------------------------------------------------------------------------------- /15-WebBrowser/11-1/app2.js: -------------------------------------------------------------------------------- 1 | // 🌟 Header object is iterable 2 | 3 | fetch("http://localhost:3000/web") 4 | .then((response) => { 5 | if ( 6 | response.ok && 7 | response.headers.get("Content-Type") === "application/json; charset=utf-8" 8 | ) { 9 | // console.log(response.headers.has("Content-Type")); 10 | for (let [name, value] of response.headers) { 11 | console.log(`${name}: ${value}`); 12 | } 13 | } else { 14 | throw new Error( 15 | `Unexpected response status ${response.status} or content type` 16 | ); 17 | } 18 | }) 19 | .catch((error) => { 20 | console.log("Error while fetching current user:", error); 21 | }); 22 | -------------------------------------------------------------------------------- /15-WebBrowser/11-1/app3.js: -------------------------------------------------------------------------------- 1 | // ✨ Setting Request Parameters 2 | // 🌟🌟 파라미터를 "URL"과 함께 전달하고 싶을 때 3 | // - searchParams 사용할 것 4 | // - Network에서 요청 헤더를 살펴볼 것 "?who_are_u=incheon" 5 | 6 | async function search(term) { 7 | let url = new URL("http://localhost:3000/web"); 8 | url.searchParams.set("who_are_u", term); 9 | let response = await fetch(url); 10 | if (!response.ok) throw new Error(response.statusText); 11 | let resultsArray = await response.json(); 12 | return resultsArray; 13 | } 14 | 15 | search("incheon").then((res) => { 16 | console.log(res); 17 | }); 18 | -------------------------------------------------------------------------------- /15-WebBrowser/11-1/app4.js: -------------------------------------------------------------------------------- 1 | // ✨ SETTTING REQUEST HEADERS (자원 요청 시 헤더 설정하기) 2 | // - 예를들면, Credential이 포함된 Authorization header를 만들 수 있음 3 | // 🌟방법🌟 4 | // fetch()의 "첫 번째 인자에 URL", "두 번째 인자에 객체(헤더)"를 넣을 것 5 | 6 | const username = "dweb"; 7 | const password = "incheon"; 8 | 9 | let authHeaders = new Headers(); 10 | // ✨ Request 헤더에 Authorization과 Dweb 필드가 추가된 것을 확인할 수 있음 11 | authHeaders.set("Authorization", `Basic ${btoa(`${username}:${password}`)}`); 12 | authHeaders.set("Dweb", `Incheon National University`); 13 | fetch("http://localhost:3000/web", { headers: authHeaders }) 14 | .then((response) => response.json()) 15 | .then((profile) => console.log(profile)); 16 | 17 | // ✨ fetch()에 인자 두 개를 전달하는 또 다른 방법 18 | // - Ruquest 생성자 사용 19 | /* 20 | let url = "http://localhost:3000/web"; 21 | let request = new Request(url, { authHeaders }); 22 | fetch(request) 23 | .then((res) => { 24 | return res.text(); 25 | }) 26 | .then((data) => { 27 | console.log(data); 28 | }); 29 | */ 30 | -------------------------------------------------------------------------------- /15-WebBrowser/11-1/app5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ✨ Client-Side 7 | 8 | 9 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /15-WebBrowser/11-1/app5.js: -------------------------------------------------------------------------------- 1 | // ✨ Server-Side 2 | 3 | const express = require("express"); 4 | const app = express(); 5 | 6 | app.get("/stream", async function (req, res) { 7 | res.write("Incheon National University ⏰"); 8 | await new Promise((resolve) => setTimeout(resolve, 1000)); 9 | res.write("Computer Science and Engineering"); 10 | await new Promise((resolve) => setTimeout(resolve, 1000)); 11 | res.write("🙋"); 12 | res.end(); 13 | }); 14 | 15 | app.get("/", function (req, res) { 16 | res.sendFile(__dirname + "/app5.html"); 17 | }); 18 | 19 | app.listen(8081, function () { 20 | console.log("server running on 8081"); 21 | }); 22 | -------------------------------------------------------------------------------- /15-WebBrowser/11-1/app6.js: -------------------------------------------------------------------------------- 1 | const data = { studentID: "202503021", name: "Park" }; 2 | 3 | fetch("http://localhost:3000/web", { 4 | method: "POST", 5 | headers: { 6 | "Content-Type": "application/json", 7 | Connection: "keep-alive", 8 | }, 9 | body: JSON.stringify(data), 10 | }) 11 | .then((response) => { 12 | if (response.status === 201) { 13 | return response.json(); 14 | } 15 | }) 16 | .then((profile) => { 17 | console.log(profile); 18 | }); 19 | -------------------------------------------------------------------------------- /15-WebBrowser/11-1/app8.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 🌟 FILE UPLOAD WITH FETCH() 7 | 8 | 9 |
    10 |
    11 | 12 | 13 |
    14 | 15 |
    16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /15-WebBrowser/11-1/app8.js: -------------------------------------------------------------------------------- 1 | // ✨✨ Do it with Express-Server 2 | // 📚📚 https://velog.io/@archivvonjang/Node.js-간단한-API-서버-만들기 3 | 4 | // Select your input type file and store it in a variable 5 | const input = document.getElementById("fileinput"); 6 | 7 | // This will upload the file after having read it 8 | const upload = (file) => { 9 | fetch("http://localhost:3000/incheon", { 10 | // Your POST endpoint 11 | method: "POST", 12 | // If you add this, upload won't work 13 | // headers: { 14 | // 'Content-Type': 'multipart/form-data', 15 | // } 16 | body: file, // This is your file object 17 | }) 18 | .then( 19 | (response) => response.json() // if the response is a JSON object 20 | ) 21 | .then( 22 | (success) => console.log(success) // Handle the success response object 23 | ) 24 | .catch( 25 | (error) => console.log(error) // Handle the error response object 26 | ); 27 | }; 28 | 29 | // Event handler executed when a file is selected 30 | const onSelectFile = () => { 31 | upload(input.files[0]); 32 | console.log(input.files[0]); 33 | }; 34 | 35 | // Add a listener on your input 36 | // It will be triggered when a file will be selected 37 | input.addEventListener("change", onSelectFile, false); 38 | -------------------------------------------------------------------------------- /15-WebBrowser/11-1/db.json: -------------------------------------------------------------------------------- 1 | { 2 | "web": [ 3 | { 4 | "id": 1, 5 | "studentID": "20201234", 6 | "name": "Kim" 7 | } 8 | ], 9 | "server": [ 10 | { 11 | "id": 1, 12 | "studentID": "20212323", 13 | "name": "Lee" 14 | } 15 | ], 16 | "blockchain": [ 17 | { 18 | "studentID": "202503021", 19 | "name": "Lee", 20 | "id": 1 21 | }, 22 | { 23 | "gender": "female", 24 | "id": 2 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /15-WebBrowser/11-1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 🌟 15.11 Networking 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /15-WebBrowser/11-1/uni.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dweb-Incheon/JS/9a06f1954fc98bf813480101f372a91b6d81d660/15-WebBrowser/11-1/uni.jpg -------------------------------------------------------------------------------- /15-WebBrowser/11-2/chatServer.js: -------------------------------------------------------------------------------- 1 | // This is server-side JavaScript, intended to be run with NodeJS. 2 | // It implements a very simple, completely anonymous chat room. 3 | // POST new messages to /chat, or GET a text/event-stream of messages 4 | // from the same URL. Making a GET request to / returns a simple HTML file 5 | // that contains the client-side chat UI. 6 | import http from "http"; 7 | import fs from "fs"; 8 | import url from "url"; 9 | 10 | // The HTML file for the chat client. Used below. 11 | const clientHTML = fs.readFileSync("./chatClient.html"); 12 | 13 | // An array of ServerResponse objects that we're going to send events to 14 | let clients = []; 15 | 16 | // Create a new server, and listen on port 8080. 17 | // Connect to http://localhost:8080/ to use it. 18 | let server = new http.Server(); 19 | server.listen(8080); 20 | 21 | // When the server gets a new request, run this function 22 | server.on("request", (request, response) => { 23 | // Parse the requested URL 24 | let pathname = url.parse(request.url).pathname; 25 | 26 | // If the request was for "/", send the client-side chat UI. 27 | if (pathname === "/") { 28 | // A request for the chat UI 29 | response.writeHead(200, { "Content-Type": "text/html" }).end(clientHTML); 30 | } 31 | // Otherwise send a 404 error for any path other than "/chat" or for 32 | // any method other than "GET" and "POST" 33 | else if ( 34 | pathname !== "/chat" || 35 | (request.method !== "GET" && request.method !== "POST") 36 | ) { 37 | response.writeHead(404).end(); 38 | } 39 | // If the /chat request was a GET, then a client is connecting. 40 | else if (request.method === "GET") { 41 | acceptNewClient(request, response); 42 | } 43 | // Otherwise the /chat request is a POST of a new message 44 | else { 45 | broadcastNewMessage(request, response); 46 | } 47 | }); 48 | 49 | // This handles GET requests for the /chat endpoint which are generated when 50 | // the client creates a new EventSource object (or when the EventSource 51 | // reconnects automatically). 52 | function acceptNewClient(request, response) { 53 | // Remember the response object so we can send future messages to it 54 | clients.push(response); 55 | 56 | // If the client closes the connection, remove the corresponding 57 | // response object from the array of active clients 58 | request.connection.on("end", () => { 59 | clients.splice(clients.indexOf(response), 1); 60 | response.end(); 61 | }); 62 | 63 | // Set headers and send an initial chat event to just this one client 64 | response.writeHead(200, { 65 | "Content-Type": "text/event-stream", 66 | Connection: "keep-alive", 67 | "Cache-Control": "no-cache", 68 | }); 69 | response.write("event: chat\ndata: Connected\n\n"); 70 | 71 | // Note that we intentionally do not call response.end() here. 72 | // Keeping the connection open is what makes Server-Sent Events work. 73 | } 74 | 75 | // This function is called in response to POST requests to the /chat endpoint 76 | // which clients send when users type a new message. 77 | async function broadcastNewMessage(request, response) { 78 | // First, read the body of the request to get the user's message 79 | request.setEncoding("utf8"); 80 | let body = ""; 81 | for await (let chunk of request) { 82 | body += chunk; 83 | } 84 | 85 | // Once we've read the body send an empty response and close the connection 86 | response.writeHead(200).end(); 87 | 88 | // Format the message in text/event-stream format, prefixing each 89 | // line with "data: " 90 | let message = "data: " + body.replace("\n", "\ndata: "); 91 | 92 | // Give the message data a prefix that defines it as a "chat" event 93 | // and give it a double newline suffix that marks the end of the event. 94 | let event = `event: chat\n${message}\n\n`; 95 | 96 | // Now send this event to all listening clients 97 | clients.forEach((client) => client.write(event)); 98 | } 99 | -------------------------------------------------------------------------------- /15-WebBrowser/11-2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | SSE Chat 4 | 5 | 6 | 7 | 8 | 12 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /15-WebBrowser/11-3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 🌟 15.11.3 WebSockets 7 | 8 | 9 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /15-WebBrowser/11-3/server.js: -------------------------------------------------------------------------------- 1 | const WebSocket = require("ws"); 2 | 3 | const wss = new WebSocket.Server({ port: 3003 }); 4 | 5 | wss.on("connection", (ws) => { 6 | console.log(`New client connected!`); 7 | 8 | ws.on("message", (data) => { 9 | console.log(`Client has sent us : ${data}`); 10 | ws.send(`${data} Me too`); 11 | }); 12 | 13 | ws.on("close", () => { 14 | console.log(`Client has disconnected`); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /15-WebBrowser/12-1/app1.js: -------------------------------------------------------------------------------- 1 | // localStorage.setItem(`name`, `incheon`); 2 | // localStorage.getItem(`name`); 3 | // localStorage.removeItem(`name`); 4 | 5 | // sessionStorage.setItem(`name`, `songdo`); 6 | // sessionStorage.getItem(`name`); 7 | // sessionStorage.setItem(`name`, `yeonsu`); //overwrite 8 | // sessionStorage.removeItem(`name`); 9 | -------------------------------------------------------------------------------- /15-WebBrowser/12-1/app2.js: -------------------------------------------------------------------------------- 1 | let names = localStorage.username; // Query a stored value. 2 | if (!names) { 3 | names = prompt("What is your name?"); // Ask the user a question. 4 | localStorage.username = names; // Store the user's response. 5 | } 6 | localStorage.clear(); 7 | -------------------------------------------------------------------------------- /15-WebBrowser/12-1/app3.js: -------------------------------------------------------------------------------- 1 | localStorage.x = 10; 2 | let x = parseInt(localStorage.x); 3 | localStorage.lastRead = new Date().toUTCString(); 4 | let lastRead = new Date(Date.parse(localStorage.lastRead)); 5 | localStorage.data = JSON.stringify(data); // Encode and store 6 | let data = JSON.parse(localStorage.data); // Retrieve and decode. 7 | -------------------------------------------------------------------------------- /15-WebBrowser/12-1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 🌟 15.12.1 local/session storage 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /15-WebBrowser/12-2/app1.js: -------------------------------------------------------------------------------- 1 | // ✨ 15.12.2 Cookies 2 | 3 | // document.cookie = "쿠키이름=쿠키값" 4 | document.cookie = `user1 = incheon`; 5 | // 만료기간을 넣어서 쿠키가 자동 만료 되도록 제작할 수 있다.(UTC time을 이용) 6 | document.cookie = 7 | `user2=songdo; expires=` + 8 | new Date("December 17, 2025 03:24:00").toUTCString(); 9 | // 파라미터를 이용하여 쿠키가 어디 브라우저에 속할 수 있을지 알려줄 수 있다. 10 | document.cookie = "user3=dweb; expires=Thu, 18 Dec 2033 12:00:00 UTC; path=/"; 11 | -------------------------------------------------------------------------------- /15-WebBrowser/12-2/app2.js: -------------------------------------------------------------------------------- 1 | // Return the document's cookies as a Map object. 2 | // Assume that cookie values are encoded with encodeURIComponent(). 3 | function getCookies() { 4 | let cookies = new Map(); // The object we will return 5 | let all = document.cookie; // Get all cookies in one big string 6 | let list = all.split("; "); // Split into individual name/value pairs 7 | for (let cookie of list) { 8 | // For each cookie in that list 9 | if (!cookie.includes("=")) continue; // Skip if there is no = sign 10 | let p = cookie.indexOf("="); // Find the first = sign 11 | let name = cookie.substring(0, p); // Get cookie name 12 | let value = cookie.substring(p + 1); // Get cookie value 13 | value = decodeURIComponent(value); // Decode the value 14 | cookies.set(name, value); // Remember cookie name and value 15 | } 16 | return cookies; 17 | } 18 | 19 | console.log(getCookies()); 20 | -------------------------------------------------------------------------------- /15-WebBrowser/12-2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 🍪 15.12.2 Cookies 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /15-WebBrowser/12-3/app1.js: -------------------------------------------------------------------------------- 1 | // 🌟 IDB - DB "생성" 2 | // version을 변경할 수 있음. 버전 값을 입력하지 않으면 1로 설정 3 | // 이미 만들어진 버전보다 더 낮은 버전의 DB를 생성할 수 없음 (에러!) 4 | 5 | // 🚨 IDB의 모든 동작은 비동기임을 기억할 것 6 | const req = indexedDB.open("inuDB", 1); 7 | 8 | req.onsuccess = function (e) { 9 | alert(`👏 Success is called`); 10 | }; 11 | 12 | // DB의 버전이 업그레이드 되는 경우 실행되는 콜백 13 | req.onupgradeneeded = function (e) { 14 | alert(`🤯 Upgrade!`); 15 | 16 | // console.log("🤯", e); 17 | // let db = e.target.result; 18 | // // 객체의 식별자 (id)로 사용될 필드를 keyPath로 지정할 수 있음 19 | // db.createObjectStore("Web", { keyPath: "name" }); 20 | // console.log("🤯", db); 21 | }; 22 | -------------------------------------------------------------------------------- /15-WebBrowser/12-3/app2.js: -------------------------------------------------------------------------------- 1 | // 🌟 IDB - DB 연결 2 | let db; 3 | const req = indexedDB.open("inuDB", 1); 4 | 5 | req.onupgradeneeded = function (e) { 6 | alert(`🤯 Upgrade!`); 7 | db = e.target.result; 8 | db.createObjectStore("Web", { keyPath: "name" }); 9 | }; 10 | 11 | req.onsuccess = function (e) { 12 | console.log(`🔥 Onsuccess`); 13 | db = e.target.result; 14 | console.log(`🔥`, db); 15 | }; 16 | 17 | req.onerror = function (e) { 18 | console.log("onerror! doesnt work"); 19 | console.dir(e); 20 | }; 21 | -------------------------------------------------------------------------------- /15-WebBrowser/12-3/app3.js: -------------------------------------------------------------------------------- 1 | // 🌟 IDB - Object Store에 데이터(객체) "저장" 2 | // 🚨 Transaction으로 데이터 저장 3 | let db; 4 | const req = indexedDB.open("inuDB", 1); 5 | 6 | req.onupgradeneeded = function (e) { 7 | alert(`🤯 Upgrade!`); 8 | db = e.target.result; 9 | db.createObjectStore("Web", { keyPath: "name" }); 10 | }; 11 | 12 | req.onsuccess = function (e) { 13 | console.log(`🔥 Onsuccess`); 14 | db = e.target.result; 15 | console.log(`🔥`, db); 16 | addItem(); 17 | }; 18 | 19 | req.onerror = function (e) { 20 | console.log("onerror! doesnt work"); 21 | console.dir(e); 22 | }; 23 | 24 | function addItem() { 25 | const item = { 26 | name: `횃불이`, 27 | student_id: `20201234`, 28 | grade: `C+`, 29 | created: new Date().getTime(), 30 | }; 31 | 32 | // 트랜잭션을 만들고 ObjectStore에 저장 (readwrite 데이터 쓸 때 사용) 33 | const objectStore = db 34 | .transaction("Web", "readwrite") 35 | .objectStore("Web") 36 | .add(item); 37 | 38 | objectStore.addEventListener(`success`, () => { 39 | console.log("😆"); 40 | }); 41 | } 42 | -------------------------------------------------------------------------------- /15-WebBrowser/12-3/app4.js: -------------------------------------------------------------------------------- 1 | // 🌟 IDB - Object Store에 저장된 데이터(객체) "조회" 2 | 3 | let db; 4 | const req = indexedDB.open("inuDB", 1); 5 | req.onupgradeneeded = function (e) { 6 | alert(`🤯 Upgrade!`); 7 | db = e.target.result; 8 | db.createObjectStore("Web", { keyPath: "name" }); 9 | }; 10 | 11 | req.onsuccess = function (e) { 12 | console.log(`🔥 Onsuccess`); 13 | db = e.target.result; 14 | 15 | const objectStore = db.transaction("Web", `readonly`).objectStore("Web"); 16 | let obj = objectStore.get(`횃불이`); 17 | console.log(obj); 18 | obj.onsuccess = function (e) { 19 | console.log(e.target.result); 20 | }; 21 | }; 22 | -------------------------------------------------------------------------------- /15-WebBrowser/12-3/app5.js: -------------------------------------------------------------------------------- 1 | // 🌟 IDB - Object Store에 저장된 데이터(객체) "삭제" 2 | 3 | let db; 4 | const req = indexedDB.open("inuDB", 1); 5 | req.onupgradeneeded = function (e) { 6 | alert(`🤯 Upgrade!`); 7 | db = e.target.result; 8 | db.createObjectStore("Web", { keyPath: "name" }); 9 | }; 10 | 11 | req.onsuccess = function (e) { 12 | console.log(`🔥 Onsuccess`); 13 | db = e.target.result; 14 | 15 | const objectStore = db.transaction("Web", `readwrite`).objectStore("Web"); 16 | let obj = objectStore.delete(`횃불이`); 17 | console.log(obj); 18 | obj.onsuccess = function (e) { 19 | console.log(`😊`, e); 20 | }; 21 | }; 22 | -------------------------------------------------------------------------------- /15-WebBrowser/12-3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ✨✨ Chapter 15.2.3 IndexedDB 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /15-WebBrowser/12-4/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | GunDB 10 | 11 | 12 |

    Todo

    13 | 14 |
    15 | 16 | 17 | 18 | 19 |
    20 | 21 | 22 | 23 |
    24 | 25 | 26 |
    27 | 28 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /15-WebBrowser/8-1/blue-robot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dweb-Incheon/JS/9a06f1954fc98bf813480101f372a91b6d81d660/15-WebBrowser/8-1/blue-robot.png -------------------------------------------------------------------------------- /15-WebBrowser/8-1/index1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Chapter 15.8. Canvas 7 | 8 | 9 |
    10 | 11 |
    12 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /15-WebBrowser/8-1/index2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Blue Robot Demo 5 | 23 | 24 | 102 | 162 | 182 |

    183 | 184 | 185 |

    186 | 187 | 201 | 202 | -------------------------------------------------------------------------------- /15-WebBrowser/8-1/index3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Canvas 7 | 8 | 9 | 10 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /6-Object/app1.js: -------------------------------------------------------------------------------- 1 | // ✨ 6.2.1 Object Literal을 이용하여 객체를 만드는 방법 2 | "use strict"; 3 | 4 | const obj = {}; // const keyword로 만든 변수는 값을 재할당 받을 수 없음 5 | obj.x = 10; // 하지만, 객체를 업데이트 하는 것은 가능 6 | //✨ 에러가 발생하는 경우: obj = { x: 10 }; 7 | 8 | let empty = {}; // An object with no properties 9 | let point = { x: 0, y: 0 }; // Two numeric properties 10 | let p2 = { x: point.x, y: point.y + 1 }; // More complex values 11 | 12 | let book = { 13 | "main title": "JavaScript", // These property names include spaces 14 | "sub-title": "The Definitive Guide", // and hyphens, so use string literals. 15 | for: "all audiences", // for is reserved, but no quotes. 16 | author: { 17 | // The value of this property is 18 | firstname: "David", // itself an object. 19 | surname: "Flanagan", 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /6-Object/app10.js: -------------------------------------------------------------------------------- 1 | // Note. 객체 o는 객체 { x: 1, y: 2, z: 3 }를 상속 2 | let o = Object.create({ x: 1, y: 2, z: 3 }); // Three enumerable own properties 3 | o.xx = 11; 4 | o.yy = 22; 5 | o.zz = 33; 6 | o.ff = function(){}; 7 | 8 | // Note. 빌트인 함수를 이용하여 Property 열거 유무 확인 9 | o.propertyIsEnumerable("toString"); // => false: not enumerable 10 | o.propertyIsEnumerable("xx"); // => true 11 | 12 | // Note. 열거할 수 있는 Property를 모두 출력 13 | for (let p in o) { 14 | // Loop through the properties 15 | console.log("😀", p); // Prints x, y, and z, but not toString 16 | } 17 | 18 | // Note. 상속받은 Property를 제외시킴 19 | for (let p in o) { 20 | if (!o.hasOwnProperty(p)) continue; // Skip inherited properties 21 | else console.log("🔥", p); 22 | } 23 | 24 | // Note. 함수 자료형을 가지는 Property를 제외시킴 25 | for (let p in o) { 26 | if (typeof o[p] === "function") continue; // Skip all methods 27 | else console.log("👿", p); 28 | } 29 | -------------------------------------------------------------------------------- /6-Object/app11.js: -------------------------------------------------------------------------------- 1 | // 🌟 첫번째 방법 2 | let target = { x: 1 }, 3 | source = { y: 2, z: 3 }; 4 | for (let key of Object.keys(source)) { 5 | target[key] = source[key]; 6 | } 7 | target; //=>{x:1,y:2,z:3} 8 | 9 | // 🌟 두번째 방법 10 | let o = { x: 1, z: 3 }; 11 | let defaults = { x: 2, y: 2 }; 12 | Object.assign(o, defaults); // overwrites everything in o with defaults 13 | o = Object.assign({}, defaults, o); // 같은 결과 14 | o = { ...defaults, ...o }; // "...spread operator" 활용, 같은 결과 15 | 16 | // 🌟 세번째 방법. 아래와 같이 함수를 만들어서 복사 17 | // Like Object.assign() but doesn't override existing properties (and also doesn't handle Symbol properties) 18 | function merge(target, ...sources) { 19 | for (let source of sources) { 20 | for (let key of Object.keys(source)) { 21 | if (!(key in target)) { 22 | // This is different than Object.assign() 23 | target[key] = source[key]; 24 | } 25 | } 26 | } 27 | return target; 28 | } 29 | Object.assign({ x: 1 }, { x: 2, y: 2 }, { y: 3, z: 4 }); // => {x:2, y: 3, z: 4} 30 | merge({ x: 1 }, { x: 2, y: 2 }, { y: 3, z: 4 }); // => {x:1, y: 2, z: 4} 31 | -------------------------------------------------------------------------------- /6-Object/app12.js: -------------------------------------------------------------------------------- 1 | let o = { x: 1, y: { z: [false, null, ""] } }; // Define a test object 2 | let s = JSON.stringify(o); // s == '{"x":1,"y":{"z": [false,null,""]}}' 3 | let p = JSON.parse(s); // p == {x: 1, y: {z: [false, null, ""]}} 4 | 5 | console.log(typeof o); 6 | console.log(typeof s); 7 | console.log(typeof p); 8 | -------------------------------------------------------------------------------- /6-Object/app13.js: -------------------------------------------------------------------------------- 1 | let o = { s: "test", n: 0 }; 2 | let a = JSON.stringify(o, null, 2); // => '{\n "s": "test",\n "n": 0\n}' 3 | 4 | console.log(a); 5 | -------------------------------------------------------------------------------- /6-Object/app14.js: -------------------------------------------------------------------------------- 1 | // If you invoke the toString() method of a basic JavaScript object, you get the string “[object Object]”: 2 | let s = { x: 1, y: 1 }.toString(); // s == "[object Object]" 3 | console.log({}.toString()); 4 | 5 | // toString()를 타입을 활용하는데 사용 6 | Object.prototype.toString.call([]); // => "[object Array]" 7 | Object.prototype.toString.call(/./); // => "[object RegExp]" 8 | Object.prototype.toString.call(() => {}); // => "[object Function]" 9 | Object.prototype.toString.call(""); // => "[object String]" 10 | Object.prototype.toString.call(0); // => "[object Number]" 11 | Object.prototype.toString.call(false); // => "[object Boolean]" 12 | 13 | // 😡 The default toString() method is not very informative. 14 | // 🌟 보통은 아래와 같이 toString 메서드를 직접 만들어 사용하게 됨 15 | // 예시 1 16 | let point = { 17 | x: 1, 18 | y: 2, 19 | toString: function () { 20 | return `🌟 ${this.x}, ${this.y}`; 21 | }, 22 | }; 23 | let res = String(point); // => "🌟 1, 2" --> toString() is used for string conversions 24 | console.log(res); 25 | 26 | // 예시 2. 아래와 같이 함수 코드를 읽어올 수 있음 27 | let ex1 = { 28 | xxx: function () { 29 | return true; 30 | }, 31 | toString: function () { 32 | return `${this.xxx}`; 33 | }, 34 | }; 35 | console.log(String(ex1)); 36 | -------------------------------------------------------------------------------- /6-Object/app15.js: -------------------------------------------------------------------------------- 1 | // 🌟 The purpose of this method is to return a localized string representation of the object. 2 | // 🌟 Date, Number, Array 클래스들은 toLocaleString()메서드를 커스터마이징 해두고 있음 3 | 4 | // ✨ toLocaleString() 활용 예시 1 5 | const date = new Date(); 6 | date.toLocaleString(); 7 | 8 | // ✨ toLocaleString() 활용 예시 2 9 | const check = 520000; 10 | check.toLocaleString(); 11 | 12 | // ✨ toLocaleString() 활용 예시 3 13 | const arr = [1, "hi", 1234567, date]; 14 | arr.toLocaleString(); 15 | 16 | // ✨ toLocaleString() 활용 예시 4 17 | let point = { 18 | x: 1000, 19 | y: 2000, 20 | toString: function () { 21 | return `(${this.x}, ${this.y})`; 22 | }, 23 | toLocaleString: function () { 24 | return `(${this.x.toLocaleString()}, 25 | ${this.y.toLocaleString()})`; 26 | }, 27 | }; 28 | point.toString(); // => "(1000, 2000)" 29 | point.toLocaleString(); // => "(1,000, 2,000)": note thousands separators 30 | -------------------------------------------------------------------------------- /6-Object/app16.js: -------------------------------------------------------------------------------- 1 | // 🌟 valueOf() 2 | // 예시 1. The Date class defines valueOf() to convert dates to numbers 3 | // and this allows Date objects to be chronologically compared with < and >. 4 | 5 | const date1 = new Date("02 Feb 1996 03:04:05 GMT"); 6 | console.log(date1.valueOf()); 7 | // Expected output: 823230245000 8 | 9 | const date2 = new Date("03 Feb 1996 03:04:05 GMT"); 10 | console.log(date1.valueOf() > date2.valueOf()); 11 | 12 | // 예시 2. 13 | let point = { 14 | x: 3, 15 | y: 4, 16 | valueOf: function () { 17 | return Math.hypot(this.x, this.y); 18 | }, 19 | }; 20 | Number(point); // => 5 --> valueOf() is used for conversions to numbers; 21 | point > 4; // => true 22 | console.log("😁", point == 5); // => false 23 | point < 6; // => true 24 | -------------------------------------------------------------------------------- /6-Object/app17.js: -------------------------------------------------------------------------------- 1 | // 🌟 Object.prototype에 toJSON() 메서드 없음 2 | // 🌟 But, JSON.stringify() method는 요청한 객체에 toJSON() method를 탐색하게 됨 3 | 4 | // 예제 1. toJSON() 메서드가 정의되지 않은 경우 5 | let o = { x: 1, y: { x: "dweb" } }; 6 | let s = JSON.stringify(o); 7 | console.log(s); 8 | 9 | // 예제 2. toJSON() 메서드가 정의된 경우 10 | let point = { 11 | x: 1, 12 | y: 2, 13 | toString: function () { 14 | return `(${this.x}, ${this.y})`; 15 | }, 16 | toJSON: function () { 17 | console.log("🏅"); 18 | return this.toString(); 19 | }, 20 | }; 21 | JSON.stringify([point]); // => '["(1, 2)"]' 22 | -------------------------------------------------------------------------------- /6-Object/app18.js: -------------------------------------------------------------------------------- 1 | // ✨ Shorthand Properties 2 | let x = 1, 3 | y = 2; 4 | let o1 = { 5 | x: x, 6 | y: y, 7 | }; 8 | 9 | // → ES6에서는 이렇게 변경할 수 있음 10 | let o2 = { x, y }; 11 | o2.x + o2.y; //=>3 12 | -------------------------------------------------------------------------------- /6-Object/app19.js: -------------------------------------------------------------------------------- 1 | // ✨ computed properties 2 | const PROPERTY_NAME = "p"; 3 | function computePropertyName() { 4 | return "p" + 2; 5 | } 6 | let o = {}; 7 | o[PROPERTY_NAME] = 1; 8 | o[computePropertyName()] = 2; 9 | 10 | // → 이런식으로 객체 리터럴에 속성을 추가할 수 있음 11 | let p = { 12 | [PROPERTY_NAME]: 1, 13 | [computePropertyName()]: 2, 14 | }; 15 | p.p1 + p.p2; // => 3 16 | -------------------------------------------------------------------------------- /6-Object/app2.js: -------------------------------------------------------------------------------- 1 | // ✨ 6.2.2 new 키워드를 이용하여 객체를 만드는 방법 2 | "use strict"; 3 | 4 | // Built-in 타입 객체는 constructor를 가짐 5 | let o = new Object(); // Create an empty object: same as {}. 6 | let a = new Array(); // Create an empty array: same as []. 7 | let d = new Date(); // Create a Date object representing the current time 8 | let r = new Map(); // Create a Map object for key/value mapping 9 | -------------------------------------------------------------------------------- /6-Object/app20.js: -------------------------------------------------------------------------------- 1 | // 🌟 ES6부터 property names은 string뿐만 아니라 symbol도 가능 2 | // ✨ 아래와 같이 Symbol() factory function을 사용하여 심볼을 생성할 수 있음 3 | // ✨ 충돌없이 객체를 확장할 수 있는 메커니즘. 4 | const extension = Symbol("my extension symbol"); // extension type은 심볼 5 | let o = { 6 | [extension]: { 7 | /* extension data stored in this object */ 8 | }, 9 | }; 10 | o[extension].x = 0; // This won't conflict with other properties of o 11 | 12 | // ----- 13 | // ✨ Object.getOwnPropertySymbols() 사용 예시 14 | const object1 = {}; 15 | const a = Symbol("a"); 16 | const b = Symbol.for("b"); 17 | 18 | object1[a] = "localSymbol"; 19 | object1[b] = "globalSymbol"; 20 | 21 | const objectSymbols = Object.getOwnPropertySymbols(object1); 22 | 23 | console.log(objectSymbols.length); 24 | // Expected output: 2 25 | -------------------------------------------------------------------------------- /6-Object/app21.js: -------------------------------------------------------------------------------- 1 | // 🌟 ... syntax : spread operator를 이용하여 객체의 Property 복사하기 2 | let position = { x: 0, y: 0 }; 3 | let dimensions = { width: 100, height: 75 }; 4 | let rect = { ...position, ...dimensions }; 5 | rect.x + rect.y + rect.width + rect.height; // => 175 6 | 7 | // ✨ ... syntax로 복사할 때, Property 이름이 중복되면??? 😃 마지막에 오는 값을 선택 8 | let o = { x: 1 }; 9 | let p = { x: 0, ...o }; 10 | p.x; // => 1: the value from object o overrides the initial value 11 | let q = { ...o, x: 2 }; 12 | q.x; // => 2: the value 2 overrides the previous value from o. 13 | 14 | // 🚨 상속된 Property는 spread되지 않음. 객체 자신의 Property만 복사되는 것을 주의 15 | let o1 = Object.create({ x: 1 }); // o inherits the property x 16 | let p1 = { ...o1 }; 17 | p1.x; // => undefined 18 | -------------------------------------------------------------------------------- /6-Object/app22.js: -------------------------------------------------------------------------------- 1 | // 🌟 메서드를 객체의 Property로 정의하려면? 2 | // ✨ ES6 이전 버전) 객체 리터럴에 function definition expression을 이용함 3 | let square = { 4 | area: function () { 5 | return this.side * this.side; 6 | }, 7 | side: 10, 8 | }; 9 | square.area(); // => 100 10 | 11 | // ✨✨ ES6 이후 버전) function 키워드와 colon을 생략할 수 있음 12 | let square1 = { 13 | area() { 14 | return this.side * this.side; 15 | }, 16 | side: 10, 17 | }; 18 | square1.area(); // => 100 19 | 20 | // ✨ 추가) 메서드 이름에 심볼을 사용할 수도 있음 21 | const METHOD_NAME = "m"; 22 | const symbol = Symbol(); 23 | let weirdMethods = { 24 | "method With Spaces"(x) { 25 | return x + 1; 26 | }, 27 | [METHOD_NAME](x) { 28 | return x + 2; 29 | }, 30 | [symbol](x) { 31 | return x + 3; 32 | }, 33 | }; 34 | weirdMethods["method With Spaces"](1); // => 2 35 | weirdMethods[METHOD_NAME](1); // => 3 36 | weirdMethods[symbol](1); // => 4 37 | -------------------------------------------------------------------------------- /6-Object/app23.js: -------------------------------------------------------------------------------- 1 | // 🌟 자바스크립트 객체는 data properties 뿐만 아니라 ✨ accessor properties 를 가질 수 있음 2 | // ✨ data properties는 name과 value로 이루어지지만 accessor properties는 getter와 setter 두 메서드를 가짐 3 | 4 | // ---------- 5 | // 예제 ① 6 | const value = 20; 7 | let o = { 8 | // An ordinary data property 9 | dataProp: value, 10 | // An accessor property defined as a pair of functions. 11 | get accessorProp() { 12 | return this.dataProp; 13 | }, 14 | set accessorProp(value) { 15 | console.log("값을 변경하셨네요"); 16 | this.dataProp = value; 17 | }, 18 | }; 19 | console.log(o.accessorProp); 20 | o.accessorProp = "Dweb"; 21 | 22 | // ---------- 23 | // 예제 ② 24 | let p = { 25 | // x and y are regular read-write data properties. 26 | x: 1.0, 27 | y: 1.0, 28 | // r is a read-write accessor property with getter and setter. 29 | // Don't forget to put a comma after accessor methods. 30 | get r() { 31 | return Math.hypot(this.x, this.y); 32 | }, 33 | set r(newvalue) { 34 | let oldvalue = Math.hypot(this.x, this.y); 35 | let ratio = newvalue / oldvalue; 36 | this.x *= ratio; 37 | this.y *= ratio; 38 | }, 39 | // theta is a read-only accessor property with getter only. 40 | get theta() { 41 | return Math.atan2(this.y, this.x); 42 | }, 43 | }; 44 | p.r; // => Math.SQRT2 45 | p.theta; // => Math.PI / 4 46 | 47 | // ---------- 48 | // 예제 ③ ✨ Accessor Property도 상속됨. 아래에서 r 속성은 상속된 프로퍼티에 의해 만들어진 것 49 | let q = Object.create(p); // A new object that inherits getters and setters 50 | q.x = 3; // Create q's own data properties 51 | q.y = 4; 52 | q.r; // => 5: ✨ the inherited accessor properties work 53 | q.theta; // => Math.atan2(4, 3) 54 | 55 | // ---------- 56 | // 예제 ④ Accessor Property를 통해 읽기/쓰기 동작을 검사할 수 있음 57 | // This object generates strictly increasing serial numbers 58 | const serialnum = { 59 | // This data property holds the next serial number. 60 | // The _ in the property name hints that it is for internal use only. 61 | _n: 0, 62 | // Return the current value and increment it 63 | get next() { 64 | return this._n++; 65 | }, 66 | // Set a new value of n, but only if it is larger than current 67 | set next(n) { 68 | if (n > this._n) this._n = n; 69 | else throw new Error("serial number can only be set to a larger value"); 70 | }, 71 | }; 72 | serialnum.next = 10; // Set the starting serial number 73 | serialnum.next; // => 10 74 | serialnum.next; // => 11: different value each time we get next 75 | -------------------------------------------------------------------------------- /6-Object/app3.js: -------------------------------------------------------------------------------- 1 | // ✨ 6.2.4 Object.create()을 이용하여 객체를 만드는 방법 2 | "use strict"; 3 | 4 | let o1 = Object.create({ x: 1, y: 2 }); // o1 inherits properties x and y. 5 | o1.x + o1.y; //=>3 6 | 7 | //o1.dweb = "inu lab"; 8 | 9 | let o2 = Object.create(null); // o2 inherits no props or methods. 10 | 11 | let o3 = Object.create(Object.prototype); // o3 is like {} or new Object(). 12 | 13 | let o = { x: "don't change this value" }; 14 | 15 | console.log("👿", Object.create(o)); 16 | console.log("😀", o); 17 | 18 | // 🌟 Guard against accidental modifications 19 | function lib(obj) { 20 | console.log(`👏🌟 ${obj.x}`); 21 | obj.x = "-------"; 22 | console.log("실수를 발생시킴", obj); 23 | for (let a in obj) { 24 | console.log(`🌟 ${obj[a]}`); 25 | } 26 | } 27 | lib(Object.create(o)); 28 | console.log("영향을 받았는지 확인", o); 29 | 30 | // 이런식으로 객체를 생성할 수도 있음 31 | let ox1 = { age: 25, i: o }; 32 | ox1.i.x = "ok if you try to modify x"; 33 | console.log("👍", ox1); 34 | console.log("🏅", o); 35 | 36 | // 이런식으로 객체를 생성할 수도 있음 37 | let ox2 = { age: 25, i: Object.create(o) }; 38 | ox2.i.x = "ok if you try to modify x"; 39 | console.log("👍", ox2); 40 | console.log("🏅", o); 41 | -------------------------------------------------------------------------------- /6-Object/app4.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | let book = { 3 | "main title": "JavaScript", // These property names include spaces 4 | "sub-title": "The Definitive Guide", // and hyphens, so use string literals. 5 | for: "all audiences", // for is reserved, but no quotes. 6 | author: { 7 | // The value of this property is 8 | firstname: "David", // itself an object. 9 | surname: "Flanagan", 10 | }, 11 | }; 12 | 13 | let author = book.author; // Get the "author" property of the book. 14 | let name = author.surname; // Get the "surname" property of the author. 15 | let title = book["main title"]; // Get the "main title" property of the book. 16 | 17 | book.edition = 7; // Create an "edition" property of book. 18 | book["main title"] = "ECMAScript"; // Change the "main title" property. 19 | 20 | //the following two JavaScript expressions have the same value 21 | console.log(book.for); 22 | console.log(book["for"]); 23 | -------------------------------------------------------------------------------- /6-Object/app5.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | function computeValue(portfolio) { 3 | let total = 0.0; 4 | for (let stock in portfolio) { 5 | // For each stock in the portfolio: 6 | let shares = portfolio[stock]; // get the number of shares 7 | let price = getQuote(stock); // look up share price 8 | total += shares * price; // add stock value to total value 9 | } 10 | return total; 11 | } 12 | 13 | // Remember 14 | let arr = ["book", "pen", "note"]; // Array Object 15 | let obj = { book: {}, pen: {}, note: {} }; 16 | 17 | for (let i of arr) { 18 | console.log(i); 19 | } 20 | for (let i in obj) { 21 | console.log("✨", i); 22 | } 23 | -------------------------------------------------------------------------------- /6-Object/app6.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // Example 1 3 | let o = {}; // o inherits object methods from Object.prototype 4 | o.x = 1; // and it now has an own property x. 5 | let p = Object.create(o); // p inherits properties from o and Object.prototype 6 | p.y = 2; // and has an own property y. 7 | let q = Object.create(p); // q inherits properties from p, o, and... 8 | q.z = 3; // ...Object.prototype and has an own property z. 9 | let f = q.toString(); // toString is inherited from Object.prototype 10 | q.x + q.y; // => 3; x and y are inherited from o and p 11 | 12 | // Example 2 13 | let unitcircle = { r: 1 }; // An object to inherit from 14 | let c = Object.create(unitcircle); // c inherits the property r 15 | c.x = 1; 16 | c.y = 1; // c defines two properties of its own 17 | c.r = 2; // c overrides its inherited property 18 | unitcircle.r; // => 1: the prototype is not affected 19 | 20 | c.__proto__.r = 100; 21 | unitcircle.r; // => 100 22 | -------------------------------------------------------------------------------- /6-Object/app7.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | let book = { 4 | "main title": "JavaScript", 5 | "sub-title": "The Definitive Guide", 6 | for: "all audiences", 7 | author: { 8 | firstname: "David", 9 | surname: "Flanagan", 10 | }, 11 | }; 12 | console.log(book.subtitle); // undefined 13 | //let len = book.subtitle.length; // !TypeError: undefined 14 | let len = undefined; 15 | if (book.subtitle) { 16 | console.log("🔥"); 17 | let len = book.subtitle.length; 18 | } 19 | 20 | let len1 = book && book.subtitle && book.subtitle.length; 21 | console.log(`👏`, Boolean(book)); 22 | // -------- 23 | // Approach 1. A verbose and explicit technique 24 | let surname = undefined; 25 | 26 | if (book) { 27 | if (book.author) { 28 | surname = book.author.surname; 29 | } 30 | } 31 | 32 | // Approach 2. A concise and idiomatic alternative to get surname or null or undefined 33 | surname = book && book.author && book.author.surname; 34 | console.log(surname); 35 | -------------------------------------------------------------------------------- /6-Object/app8.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | let book = { 4 | "main title": "JavaScript", 5 | "sub-title": "The Definitive Guide", 6 | for: "all audiences", 7 | author: { 8 | firstname: "David", 9 | surname: "Flanagan", 10 | }, 11 | }; 12 | 13 | delete book.author; // The book object now has no author property. 14 | delete book["main title"]; // Now it doesn't have "main title", either. 15 | 16 | let o = { x: 1 }; // o has own property x and inherits property toString 17 | console.log(o); 18 | let suc = delete o.x; // => true: deletes property x 19 | console.log(o); 20 | console.log("✨ true:false", suc); 21 | 22 | delete o.x; // => true: does nothing (x doesn't exist) but true anyway 23 | delete o.toString; // => true: does nothing (toString isn't an own property) 24 | delete 1; // => true: nonsense, but true anyway 25 | 26 | // Prototype으로부터 상속받은 property가 삭제되진 않음 (Query와는 다름) 27 | let obj = Object.create({ x: 1 }); 28 | 29 | let succeed = delete obj.x; 30 | console.log(obj.__proto__); 31 | 32 | // In strict mode, all these deletions throw TypeError instead of returning false 33 | delete Object.prototype; // => false: property is non-configurable 34 | var x = 1; // Declare a global variable 35 | delete globalThis.x; // => false: can't delete this property 36 | function f() {} // Declare a global function 37 | delete globalThis.f; // => false: can't delete this property either 38 | -------------------------------------------------------------------------------- /6-Object/app9.js: -------------------------------------------------------------------------------- 1 | let o = { x: 1 }; 2 | 3 | // in operator → It returns true if the object has an own property or an inherited property by that name. 4 | if ("x" in o) console.log("😀"); // => true: o has an own property "x" 5 | console.log("y" in o); // => false: o doesn't have a property "y" 6 | "toString" in o; // => true: o inherits a toString property 7 | 8 | o.hasOwnProperty("x"); // => true: o has an own property x 9 | o.hasOwnProperty("y"); // => false: o doesn't have a property y 10 | o.hasOwnProperty("toString"); // => false: toString is an inherited property 11 | 12 | o.propertyIsEnumerable("x"); // => true: o has an own enumerable property x 13 | o.propertyIsEnumerable("toString"); // => false: not an own property 14 | Object.prototype.propertyIsEnumerable("toString"); // => false: not enumerable 15 | 16 | o.x !== undefined; // => true: o has a property x 17 | o.y !== undefined; // => false: o doesn't have a property y 18 | o.toString !== undefined; // => true: o inherits a toString property 19 | 20 | let o1 = { x: undefined }; // Property is explicitly set to undefined 21 | o1.x !== undefined; // => false: property exists but is undefined 22 | o1.y !== undefined; // => false: property doesn't even exist 23 | "x" in o1; // => true: the property exists 24 | "y" in o1; // => false: the property doesn't exist 25 | delete o1.x; // Delete the property x 26 | "x" in o1; // => false: it doesn't exist anymore 27 | -------------------------------------------------------------------------------- /6-Object/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ✨✨ Chapter 6. Objects 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /7-Arrays/app1.js: -------------------------------------------------------------------------------- 1 | // 🌟 Array를 만드는 첫번째 방법. Array Literals 2 | 3 | //-------- 4 | // 예시 1 5 | let empty = []; // An array with no elements 6 | let primes = [2, 3, 5, 7, 11]; // An array with 5 numeric elements; 7 | let misc = [1.1, true, "a"]; // 3 elements of various types + trailing comma 8 | 9 | //-------- 10 | // 예시 2. ✨ 어레이 리터럴에 상수만 포함할 필요도 없음 11 | let base = 1024; 12 | let table = [base, base + 1, base + 2, base + 3]; 13 | console.log(table); 14 | base = 3; 15 | console.log(table); // 🌟 배열 원소 변경 안됨!! 16 | 17 | //-------- 18 | // 예시 3. ✨ 겍체 리터럴, 어레이 리터럴을 포함할 수도 있음 19 | let b = [ 20 | [1, { x: 1, y: 2 }], 21 | [2, { x: 3, y: 4 }], 22 | ]; 23 | 24 | //-------- 25 | // 예시 3. ✨ comma를 이용해서 비워둘 수 있음 (length에는 카운트 됨) 26 | let count = [1, , 3]; // Elements at indexes 0 and 2. No element at index 1 27 | console.log(count); 28 | let undefs = [, ,]; // An array with no elements but a length of 2 29 | console.log(undefs); 30 | -------------------------------------------------------------------------------- /7-Arrays/app10.js: -------------------------------------------------------------------------------- 1 | let letters = [..."Hello world"]; // An array of letters 2 | let everyother = ""; 3 | for (let [index, letter] of letters.entries()) { 4 | // console.log(index, letter); 5 | if (index % 2 === 0) everyother += letter; // letters at even indexes 6 | } 7 | everyother; // => "Hlowrd" 8 | -------------------------------------------------------------------------------- /7-Arrays/app11.js: -------------------------------------------------------------------------------- 1 | // 🌟 Array의 forEach() 메서드에 함수를 넘겨서 사용 2 | // ✨ forEach() invokes your function once on each element of the array: 3 | 4 | // Unlike the for/of loop 5 | // the forEach() is aware of sparse arrays and does not invoke your function for elements that are not there. 6 | let letters = [..."Hello world"]; // An array of letters 7 | let uppercase = ""; 8 | letters.forEach((letter) => { 9 | // Note arrow function syntax here 10 | uppercase += letter.toUpperCase(); 11 | }); 12 | uppercase; // => "HELLO WORLD" 13 | -------------------------------------------------------------------------------- /7-Arrays/app12.js: -------------------------------------------------------------------------------- 1 | let letters = [..."Hello world"]; // An array of letters 2 | let vowels = ""; 3 | for (let i = 0; i < letters.length; i++) { 4 | // For each index in the array 5 | let letter = letters[i]; // Get the element at that index 6 | if (/[aeiou]/.test(letter)) { 7 | // Use a regular expression test 8 | vowels += letter; // If it is a vowel, remember it 9 | } 10 | } 11 | vowels; // => "eoo" 12 | 13 | // ✨ 아래와 같이 undefined 원소는 반복 시 스킵할 필요가 있음 14 | let a = []; 15 | a[100000] = "👍"; 16 | for (let i = 0; i < a.length; i++) { 17 | if (a[i] === undefined) continue; // Skip undefined + nonexistent elements 18 | // loop body here 19 | console.log(a[i]); 20 | } 21 | -------------------------------------------------------------------------------- /7-Arrays/app13.js: -------------------------------------------------------------------------------- 1 | // 🌟 Array Iterator Methods 2 | // ✨ forEach() 3 | 4 | let data = [1, 2, 3, 4, 5], 5 | sum = 0; 6 | // Compute the sum of the elements of the array 7 | data.forEach((value) => { 8 | sum += value; 9 | }); // sum == 15 10 | // Now increment each array element 11 | data.forEach(function (v, i, a) { 12 | console.log(v, i, a); 13 | a[i] = v + 1; 14 | }); // 🔥 data 배열이 변경됨. data == [2,3,4,5,6] 15 | -------------------------------------------------------------------------------- /7-Arrays/app14.js: -------------------------------------------------------------------------------- 1 | // 🌟 Array Iterator Methods 2 | // ✨ map() 3 | 4 | // map()은 forEach()와 달리 new array (b) 를 반환함. invoke한 array에 영향 없음 (a 배열) 5 | let a = [1, 2, 3]; 6 | let b = a.map((x) => x * x); // => [1, 4, 9]: the function takes input x and returns x*x 7 | -------------------------------------------------------------------------------- /7-Arrays/app15.js: -------------------------------------------------------------------------------- 1 | // 🌟 Array Iterator Methods 2 | // ✨ filter() → 조건이 true 이면 필터링됨 3 | 4 | let a = [5, 4, 3, 2, 1]; 5 | 6 | let b = a.filter((x) => x < 3); // => [2, 1]; values less than 3 7 | 8 | let c = a.filter((v, k) => { 9 | console.log("value", v, "index", k); 10 | return k % 2 === 0; 11 | }); // => [5, 3, 1]; every other value 12 | 13 | // ✨✨✨ 문법 주의할 것. {}제거 후 return 키워드를 사용하지 않음 14 | let d = a.filter((v, k) => k % 2 === 0); 15 | 16 | // ✨ sparse array에 사용하면, missing element를 스킵하기 때문에 dense array를 만들 수 있음 17 | let sparse1 = [1, , 10]; 18 | let dense1 = sparse1.filter(() => true); 19 | 20 | let sparse2 = [1, , null, 10]; 21 | let dense2 = sparse2.filter((x) => x !== undefined && x !== null); 22 | -------------------------------------------------------------------------------- /7-Arrays/app16.js: -------------------------------------------------------------------------------- 1 | // 🌟 Array Iterator Methods 2 | // ✨ find() & findIndex() 3 | 4 | // 매칭되는 첫번째 원소의 값을 찾아서 위치를 반환해 줌. 매칭되는 값이 없으면? undefined or -1을 반환함 5 | let a = [1, 2, 3, 4, 5]; 6 | // 인덱스 반환 7 | a.findIndex((x) => x === 3); // => 2; the value 3 appears at index 2 8 | a.findIndex((x) => x < 0); // => -1; no negative numbers in the array 9 | // 값 반환 10 | a.find((x) => x % 5 === 0); // => 5: this is a multiple of 5 11 | a.find((x) => x % 7 === 0); // => undefined: no multiples of 7 in the array 12 | -------------------------------------------------------------------------------- /7-Arrays/app17.js: -------------------------------------------------------------------------------- 1 | // 🌟 Array Iterator Methods 2 | // ✨ every() and some() 3 | 4 | // 😀 mathematical 관점에서 every() method 는 “for all” quantifier ∀ 과 같은 의미를 지님 5 | // 즉, 모든 원소에 대해 조건이 참이면 true를 반환함 6 | let a = [1, 2, 3, 4, 5]; 7 | a.every((x) => x < 10); // => true: all values are < 10. 8 | a.every((x) => x % 2 === 0); // => false: not all values are even. 9 | 10 | // 😃 mathematical 관점에서 some() method 는 “there exists” quantifier ∃ 와 같은 의미를 지님 11 | // 즉, 적어도 하나의 원소가 조건을 만족시키면 true를 반환함 12 | let b = [1, 2, 3, 4, 5]; 13 | b.some((x) => x % 2 === 0); // => true; a has some even numbers. 14 | b.some(isNaN); // => false; a has no non-numbers. "not a number" isNaN()은 number인 경우 false 반환 15 | -------------------------------------------------------------------------------- /7-Arrays/app18.js: -------------------------------------------------------------------------------- 1 | // 🌟 Array Iterator Methods 2 | // ✨ reduce() & reduceRight() 3 | // ✨ single value를 만들기 위해서 배열의 원소들을 결합함 4 | 5 | // 😀 reduce() 메서드는 두 개의 인자를 취할 수 있고 reduced value를 리턴함 6 | // → 첫번째 인자는 reduction operation을 수행하는 함수. 두번째 인자는 첫번째 인자의 initial value 7 | let a = [1, 2, 3, 4, 5]; 8 | a.reduce((x, y) => x + y, 0); // => 15; the sum of the values 9 | a.reduce((x, y) => x * y, 1); // => 120; the product of the values 10 | a.reduce((x, y) => (x > y ? x : y)); // => 5; the largest of the values 11 | 12 | // 😀 reduceRight()는 highest index에서 lowest index로 동작하는 것을 제외하면, reduce() 와 동일함 13 | // 예시) Compute 2^(3^4). Exponentiation has right-to-left precedence 14 | // 아래 두 결과는 다름 15 | let b = [2, 3, 4]; 16 | b.reduceRight((acc, val) => Math.pow(val, acc)); // => 2.4178516392292583e+24 17 | b.reduce((acc, val) => { 18 | console.log(acc, val); 19 | return Math.pow(val, acc); 20 | }); 21 | -------------------------------------------------------------------------------- /7-Arrays/app19.js: -------------------------------------------------------------------------------- 1 | // 🌟🌟 Flattening arrays with flat() and flatMap() 2 | 3 | // ✨ flat() 메서드는 배열 원소들을 "flattened" 하게 한 뒤 새로운 배열을 반환함 4 | // 예시 ①. 아래와 같이 array가 nesting 되어 있는 경우 argument를 전달하지 않으면 단지 하나의 level만 펼침 5 | [1, [2, 3]].flat(); // => [1, 2, 3] 6 | [1, [2, [3]]].flat(); // => [1, 2, [3]] 7 | 8 | // 예시 ②. 중첩된 경우 펼치고 싶은만큼 인자 값을 전달할 것 9 | let a = [1, [2, [3, [4]]]]; 10 | a.flat(1); // => [1, 2, [3, [4]]] 11 | a.flat(2); // => [1, 2, 3, [4]] 12 | a.flat(3); // => [1, 2, 3, 4] 13 | a.flat(4); // => [1, 2, 3, 4] 14 | 15 | // ✨ flatMap() 메서드는 map() 메서드와 flat() 동작을 함께 함. 즉, 배열을 펼치면서 각 원소에 연산을 수행할 수 있음 16 | // 예시 ①. 17 | let phrases = ["hello world", "the definitive guide"]; 18 | let words = phrases.flatMap((phrase) => phrase.split(" ")); // 공백으로 구분 19 | words; // => ["hello", "world", "the", "definitive", "guide"]; 20 | 21 | // 예시 ②. 22 | // Map non-negative numbers to their square roots 23 | [-2, -1, 1, 2].flatMap((x) => (x < 0 ? [] : Math.sqrt(x))); // => [1, 2**0.5] 24 | // map() 메서드를 이용하면? 25 | [-2, -1, 1, 2].map((x) => (x < 0 ? [] : Math.sqrt(x))); // => [[], [], 1, 2**0.5] 26 | -------------------------------------------------------------------------------- /7-Arrays/app2.js: -------------------------------------------------------------------------------- 1 | // 🌟🌟 Array를 만드는 두번째 방법. Spread Operator 2 | 3 | // -------- 4 | // 예제 1. 배열 b에 a의 원소가 포함됨 5 | let a = [1, 2, 3]; 6 | let b = [0, ...a, 4]; //b==[0,1,2,3,4] 7 | 8 | // 예제 2. ✨ Shallow Copy!! 복사본을 변경해도 원본에 영향을 미치지 않는다. 9 | let original = [1, 2, 3]; 10 | let copy = [...original]; 11 | copy[0] = 0; // Modifying the copy does not change the original 12 | original[0]; // => 1 13 | 14 | // 예제 3. You can turn any string into an array of single-character strings: 15 | let digits = [..."0123456789ABCDEF"]; 16 | digits; // => ["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"] 17 | 18 | // 예제 4. Array에서 중복원소를 제거하는 방법. Array를 Set으로 Convertinggkf 할 것. new Set(letters) → Set이 만들어짐 19 | let letters = [..."hello world"]; 20 | [...new Set(letters)]; // => ["h","e","l","o","","w","r","d"] 21 | -------------------------------------------------------------------------------- /7-Arrays/app20.js: -------------------------------------------------------------------------------- 1 | // 🌟 Adding arrays with concat() 2 | 3 | // ✨ concat() 메서드는 두 배열을 합쳐서 새로운 배열 반환 4 | let a = [1, 2, 3]; 5 | a.concat(4, 5); // => [1,2,3,4,5] 6 | a.concat([4, 5], [6, 7]); // => [1,2,3,4,5,6,7]; arrays are flattened 7 | a.concat(4, [5, [6, 7]]); // => [1,2,3,4,5,[6,7]]; but not nested arrays 8 | a; // => [1,2,3]; the original array is unmodified 9 | -------------------------------------------------------------------------------- /7-Arrays/app21.js: -------------------------------------------------------------------------------- 1 | // 🌟 Stacks and Queues with push(), pop(), shift(), and unshift() 2 | 3 | // ✨ push(), pop() 메서드 4 | let stack = []; // stack == [] 5 | stack.push(1, 2); // stack == [1,2]; 6 | stack.pop(); // stack == [1]; returns 2 7 | stack.push(3); // stack == [1,3] 8 | stack.pop(); // stack == [1]; returns 3 9 | stack.push([4, 5]); // stack == [1,[4,5]] 10 | stack.pop(); // stack == [1]; returns [4,5] 11 | stack.pop(); // stack == []; returns 1 12 | 13 | // ✨ array를 push할 때 flatten 되지 않음. 다음과 같이 배열의 원소만 push할 수 있음 14 | let a = [10]; 15 | let values = [1, 2, 3]; 16 | a.push(...values); // a = [10, 1, 2, 3] 17 | 18 | // ✨ unshift(), shift() 메서드는 각각 push(), pop() 메서드와 유사함. 다만, 반대쪽 (beginning)에서 push, pop이 일어남 19 | let q = []; 20 | q.push(1, 2); 21 | q.shift(); 22 | q.push(3); 23 | q.unshift(100, 101); 24 | q.shift(); 25 | q.shift(); 26 | -------------------------------------------------------------------------------- /7-Arrays/app22.js: -------------------------------------------------------------------------------- 1 | // 🌟 Subarrays with slice(), splice(), fill(), and copyWithin() 2 | 3 | // ✨ slice() 메서드는 slice (subarray)를 반환 4 | // 슬라이스의 처음과 끝을 알려주는 두 인자 값을 취함. 첫번째 인자 값의 원소는 포함하고 두번째 인자 값의 원소는 포함시키지 않음 5 | let a = [1, 2, 3, 4, 5]; 6 | a.slice(0, 3); // Returns [1,2,3] 7 | a.slice(3); // Returns [4,5] 8 | 9 | // 인자 값이 음수이면? -1이면 마지막 원소를 의미. -2이면 마지막에서 하나 앞을 의미, -3은 -2의 이전 원소 10 | a.slice(1, -1); // Returns [2,3,4] 11 | a.slice(-3, -2); // Returns [3] 12 | -------------------------------------------------------------------------------- /7-Arrays/app23.js: -------------------------------------------------------------------------------- 1 | // 🌟 Array Searching and Sorting Methods 2 | // ✨ indexOf() and lastIndexOf() : 찾고자 하는 원소의 위치를 반환함. 찾을 수 없다면 -1 3 | // ✨ lastIndexOf()는 마지막부터 탐색함 4 | let a = [0, 1, 2, 1, 0]; 5 | a.indexOf(1); // => 1: a[1] is 1 6 | a.lastIndexOf(1); // => 3: a[3] is 1 7 | a.indexOf(3); // => -1: no element has value 3 8 | 9 | // 객체를 탐색하는 경우, reference 가 같은지 비교하여 위치를 알려줌 10 | let obj = { x: 1, y: 2 }; 11 | let b = [0, 1, 2, obj, 3]; 12 | console.log("👏", b.indexOf(obj)); 13 | 14 | // 두 번째 인자 값을 주게 되면 찾고자 하는 "시작" 범위를 설정하는 것 15 | console.log(a.indexOf(2)); 16 | console.log(a.indexOf(2, 3)); // 3번째 인덱스 이후에는 원소 2가 존재하지 않음 17 | -------------------------------------------------------------------------------- /7-Arrays/app24.js: -------------------------------------------------------------------------------- 1 | let a = {}; // Start with a regular empty object 2 | // Add properties to make it "array-like" 3 | let i = 0; 4 | while (i < 10) { 5 | a[i] = i * i; 6 | i++; 7 | } 8 | a.length = i; // 🌟 length property를 추가 9 | 10 | // Now iterate through it as if it were a real array 11 | let total = 0; 12 | for (let j = 0; j < a.length; j++) { 13 | total += a[j]; 14 | } 15 | -------------------------------------------------------------------------------- /7-Arrays/app25.js: -------------------------------------------------------------------------------- 1 | let a = { 0: "a", 1: "b", 2: "c", length: 3 }; // An array-like object 2 | Array.prototype.join.call(a, "+"); // => "a+b+c" 3 | Array.prototype.map.call(a, (x) => x.toUpperCase()); // => 배열을 반환. ["A","B","C"] 4 | Array.prototype.slice.call(a, 0); // => ["a","b","c"]: true array copy 5 | Array.from(a); // => ["a","b","c"]: easier array copy 6 | -------------------------------------------------------------------------------- /7-Arrays/app3.js: -------------------------------------------------------------------------------- 1 | // 🌟🌟 Array를 만드는 두번째 방법. Array() Constructor 활용 2 | // Constructor를 Invoke하는 세 가지 예제 3 | 4 | // 예제 1. 원소가 없는 Empty Array 5 | let a = new Array(); 6 | 7 | // 예제 2. Array의 length를 명시하기 8 | let b = new Array(10); 9 | 10 | // 예제 3. 11 | let c = new Array(5, 4, 3, 2, 1, "testing, testing"); 12 | -------------------------------------------------------------------------------- /7-Arrays/app4.js: -------------------------------------------------------------------------------- 1 | // 🌟🌟 Array를 만드는 두번째 방법. Array Factory Method : ① Array.of() and ② Array.form() 2 | 3 | // ⛔️ Array(10), 여기서 10은 length를 의미함 4 | // ✨ 그러나 Array.of(10), 여기서 10은 원소를 의미함 5 | Array.of(); // => []; returns empty array with no arguments 6 | Array.of(10); // => [10]; can create arrays with a single numeric argument 7 | Array.of(1, 2, 3); // => [1, 2, 3] 8 | 9 | // ✨ Array.from() 10 | // Argument로 iterable or array-like object를 입력 받음 11 | // Iterable Object? for..of 반복문을 적용할 수 있음 (뒤에서 학습할 예정) 12 | let original = [1, 2, 3]; 13 | let copy = Array.from(original); 14 | 15 | let arraylike = new Set(original); 16 | let truearray = Array.from(arraylike); 17 | 18 | for (let a of arraylike) { 19 | console.log(`✨ ${a}`); 20 | } 21 | -------------------------------------------------------------------------------- /7-Arrays/app5.js: -------------------------------------------------------------------------------- 1 | let a = ["world"]; // Start with a one-element array 2 | let value = a[0]; // Read element 0 3 | a[1] = 3.14; // Write element 1 4 | let i = 2; 5 | a[i] = 3; // Write element 2 6 | a[i + 1] = "hello"; // Write element 3 7 | a[a[i]] = a[0]; // Read elements 0 and 2, write 8 | 9 | a.length; // => 4 10 | 11 | let o = {}; // Create a plain object 12 | o[1] = "one"; // Index it with an integer 13 | o["1"]; // => "one"; numeric and string property names are the same 14 | 15 | a[-1.23] = true; // This creates a property named "-1.23" 16 | a["1000"] = 0; // This the 1001st element of the array 17 | a[1.0] = 1; // Array index 1. Same as a[1] = 1; 18 | 19 | let b = [true, false]; // This array has elements at indexes 0 and 1 20 | b[2]; // => undefined; no element at this index. 21 | b[-1]; // => undefined; no property with this name. 22 | -------------------------------------------------------------------------------- /7-Arrays/app6.js: -------------------------------------------------------------------------------- 1 | let a = new Array(5); // No elements, but a.length is 5. 2 | a = []; // Create an array with no elements and length = 0. 3 | a[1000] = 0; // Assignment adds one element but sets length to 1001. 4 | 5 | let a1 = [,]; // This array has no elements and length 1 6 | let a2 = [undefined]; // This array has one undefined element 7 | 0 in a1; // => false: a1 has no element with index 0 8 | 0 in a2; // => true: a2 has the undefined value at index 0 9 | -------------------------------------------------------------------------------- /7-Arrays/app7.js: -------------------------------------------------------------------------------- 1 | [].length; 2 | ["a", "b", "c"].length; 3 | 4 | a = [1, 2, 3, 4, 5]; // Start with a 5-element array. 5 | a.length = 3; // a is now [1,2,3]. 6 | a.length = 0; // Delete all elements. a is []. 7 | a.length = 5; // Length is 5, but no elements, like new Array(5) 8 | -------------------------------------------------------------------------------- /7-Arrays/app8.js: -------------------------------------------------------------------------------- 1 | let a = []; // Start with an empty array. 2 | a[0] = "zero"; // And add elements to it. 3 | a[1] = "one"; 4 | 5 | let b = []; // Start with an empty array 6 | b.push("zero"); // Add a value at the end. a = ["zero"] 7 | b.push("one", "two"); // Add two more values. a = ["zero", "one", "two"] 8 | 9 | let c = [1, 2, 3]; 10 | delete c[2]; // a now has no element at index 2 11 | 2 in c; // => false: no array index 2 is defined 12 | c.length; // => 3: delete does not affect array length 13 | -------------------------------------------------------------------------------- /7-Arrays/app9.js: -------------------------------------------------------------------------------- 1 | let letters = [..."Hello world"]; // An array of letters 2 | let string = ""; 3 | for (let letter of letters) { 4 | string += letter; 5 | } 6 | string; // => "Hello world"; we reassembled the original text 7 | 8 | // ✨ Sparse Array에서의 원소는 undefined로 확인됨 9 | let letter2 = [..."Hello world", , 10]; 10 | for (let l of letter2) { 11 | console.log(l); 12 | } 13 | -------------------------------------------------------------------------------- /7-Arrays/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ✨✨ Chapter 7. Arrays 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /8-Functions/app1.js: -------------------------------------------------------------------------------- 1 | // 🌟 8.1.1. Function Declarations 2 | // Print the name and value of each property of o. Return undefined. 3 | "use strict"; 4 | 5 | console.log(`🔥 ${factorial(10)}`); //hoisting 6 | 7 | function printprops(o) { 8 | for (let p in o) { 9 | console.log(`${p}: ${o[p]}\n`); 10 | } 11 | } 12 | // Compute the distance between Cartesian points (x1,y1) and (x2,y2). 13 | function distance(x1, y1, x2, y2) { 14 | let dx = x2 - x1; 15 | let dy = y2 - y1; 16 | return Math.sqrt(dx * dx + dy * dy); 17 | } 18 | // A recursive function (one that calls itself) that computes factorials 19 | // Recall that x! is the product of x and all positive integers less than it. 20 | function factorial(x) { 21 | if (x <= 1) return 1; 22 | return x * factorial(x - 1); 23 | } 24 | -------------------------------------------------------------------------------- /8-Functions/app10.js: -------------------------------------------------------------------------------- 1 | // 🌟 8.3.2 Rest Parameters and Variable-Length Argument Lists 2 | "use strict"; 3 | 4 | function max(first = -Infinity, ...rest) { 5 | let maxValue = first; // Start by assuming the first arg is biggest 6 | // Then loop through the rest of the arguments, looking for bigger 7 | console.log(first); 8 | console.log(rest); 9 | for (let n of rest) { 10 | if (n > maxValue) { 11 | maxValue = n; 12 | } 13 | } 14 | // Return the biggest 15 | return maxValue; 16 | } 17 | max(1, 10, 100, 2, 3, 1000, 4, 5, 6); // => 1000 18 | -------------------------------------------------------------------------------- /8-Functions/app11.js: -------------------------------------------------------------------------------- 1 | // 🌟 8.3.3 The Arguments Object 2 | "use strict"; 3 | 4 | // "use strict"를 선언하는 순간 arguments는 예약어 (reserved word)가 됨 5 | // let arguments = 10; 6 | 7 | function max(...args) { 8 | let maxValue = -Infinity; 9 | // Loop through the arguments, looking for, and remembering, the biggest. 10 | console.log(args); 11 | for (let i = 0; i < arguments.length; i++) { 12 | if (arguments[i] > maxValue) maxValue = arguments[i]; 13 | } 14 | // Return the biggest 15 | return maxValue; 16 | } 17 | let res = max(1, 10, 100, 2, 3, 1000, 4, 5, 6); // => 1000 18 | console.log(res); 19 | -------------------------------------------------------------------------------- /8-Functions/app12.js: -------------------------------------------------------------------------------- 1 | // 🌟 8.3.4 The Spread Operator for Function Calls 2 | "use strict"; 3 | // let numbers = [5, 2, 10, -1, 9, 100, 1]; 4 | // Math.min(...numbers); // => -1 5 | 6 | let incheon = timed(dweb); //timed 함수로부터 함수를 전달받음 7 | 8 | const arr = Array.from({ length: 100000 }, () => 1); // i(index) 1씩 증가 9 | incheon(arr); 10 | 11 | function dweb(arg) { 12 | let sum = 0; 13 | for (let i of arg) sum += i; 14 | console.log(`👏 ${sum}`); 15 | } 16 | // This function takes a function and returns a wrapped version 17 | // 🔥 Dweb 함수를 평가함 18 | function timed(f) { 19 | return function (...args) { 20 | // Collect args into a rest parameter array 21 | console.log(`Entering function ${f.name}`); 22 | let startTime = Date.now(); 23 | try { 24 | // Pass all of our arguments to the wrapped function 25 | return f(...args); // 🌟 Spread the args back out again 26 | } finally { 27 | // Before we return the wrapped return value, print elapsed time. 28 | console.log(`Exiting ${f.name} after ${Date.now() - startTime}ms`); 29 | } 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /8-Functions/app14.js: -------------------------------------------------------------------------------- 1 | // 🌟 8.4 Functions as Values 2 | "use strict"; 3 | 4 | // 함수 정의 5 | function square(x) { 6 | return x * x; 7 | } 8 | 9 | // 😯 ① 변수에 대입 가능 10 | let s = square; // Now s refers to the same function that square does 11 | square(4); // => 16 12 | s(4); // => 16 13 | 14 | // 😯 ② 객채의 프로퍼티에 함수 대입 15 | let o = { 16 | square: function (x) { 17 | return x * x; 18 | }, 19 | }; // An object literal 20 | let y = o.square(16); 21 | 22 | // 😯 ③ 배열 원소에 함수 넣는 상황. 이러한 경우 함수 이름도 필요 없음 23 | let a = [(x) => x * x, 20]; // An array literal 24 | a[0](a[1]); // => 400 25 | -------------------------------------------------------------------------------- /8-Functions/app15.js: -------------------------------------------------------------------------------- 1 | // 🌟 8.4 Functions as Values 2 | "use strict"; 3 | 4 | let a = [33, 4, 1111, 222]; 5 | a.sort(); // a == [1111, 222, 33, 4]; 6 | 7 | a.sort(function (a, b) { 8 | // Pass a comparator function 9 | return a - b; // Returns < 0, 0, or > 0, depending on order 10 | }); // a == [4, 33, 222, 1111]; numerical order 11 | console.log(a); 12 | 13 | a.sort((a, b) => b - a); // a == [1111, 222, 33, 4]; reverse numerical order 14 | console.log(a); 15 | 16 | let arr = ["b", "a", "d", "c"]; 17 | arr.sort((x, y) => { 18 | if (x > y) return 1; 19 | else return -1; 20 | }); 21 | console.log("👏", arr); 22 | -------------------------------------------------------------------------------- /8-Functions/app16.js: -------------------------------------------------------------------------------- 1 | // 🌟 8.4 Functions as Values 2 | // We define some simple functions here 3 | function add(x, y) { 4 | return x + y; 5 | } 6 | function subtract(x, y) { 7 | return x - y; 8 | } 9 | function multiply(x, y) { 10 | return x * y; 11 | } 12 | function divide(x, y) { 13 | return x / y; 14 | } 15 | 16 | // Here's a function that takes one of the preceding functions // as an argument and invokes it on two operands 17 | function operate(operator, operand1, operand2) { 18 | return operator(operand1, operand2); 19 | } 20 | // We could invoke this function like this to compute the value (2+3) + (4*5): 21 | let i = operate(add, operate(add, 2, 3), operate(multiply, 4, 5)); 22 | 23 | // 🌟 더 나은 방법 24 | // For the sake of the example, we implement the simple functions again, 25 | // this time within an object literal; 26 | const operators = { 27 | add: (x, y) => x + y, 28 | subtract: (x, y) => x - y, 29 | multiply: (x, y) => x * y, 30 | divide: (x, y) => x / y, 31 | pow: Math.pow, // This works for predefined functions too 32 | }; 33 | 34 | // This function takes the name of an operator, looks up that operator; 35 | // in the object, and then invokes it on the supplied operands. Note 36 | // the syntax used to invoke the operator function. 37 | function operate2(operation, operand1, operand2) { 38 | if (typeof operators[operation] === "function") { 39 | return operators[operation](operand1, operand2); 40 | } else throw "unknown operator"; 41 | } 42 | 43 | operate2("add", "hello", operate2("add", " ", "world")); // => "hello world" 44 | operate2("pow", 10, 2); // => 100 45 | -------------------------------------------------------------------------------- /8-Functions/app17.js: -------------------------------------------------------------------------------- 1 | // 🌟 8.4.1 Defining Your Own Function Properties 2 | 3 | // Initialize the counter property of the function object. 4 | // Function declarations are hoisted so we really can 5 | // do this assignment before the function declaration. 6 | uniqueInteger.counter = 0; 7 | // This function returns a different integer each time it is called. 8 | // It uses a property of itself to remember the next value to be returned. 9 | 10 | function uniqueInteger() { 11 | return uniqueInteger.counter++; // Return and increment counter property 12 | } 13 | uniqueInteger(); // => 0 uniqueInteger() // => 1 14 | -------------------------------------------------------------------------------- /8-Functions/app18.js: -------------------------------------------------------------------------------- 1 | // 🌟 8.4.1 Defining Your Own Function Properties 2 | "use strict"; 3 | // Compute factorials and cache results as properties of the function itself. 4 | function factorial(n) { 5 | if (Number.isInteger(n) && n > 0) { 6 | // Positive integers only 7 | if (!(n in factorial)) { 8 | // If no cached result 9 | factorial[n] = n * factorial(n - 1); // Compute and cache it 10 | } 11 | return factorial[n]; // Return the cached result 12 | } else { 13 | return NaN; 14 | // If input was bad 15 | } 16 | } 17 | 18 | factorial[1] = 1; // Initialize the cache to hold this base case. 19 | factorial(6); // => 720 20 | factorial[5]; // => 120; the call above caches this value 21 | -------------------------------------------------------------------------------- /8-Functions/app19.js: -------------------------------------------------------------------------------- 1 | // 🌟 Functions as Namespaces 2 | 3 | // 이 부분을 합치려는 코드로 가정할 것 4 | 5 | // let global = "Dweb"; 6 | // function dweb() { 7 | // console.log("🌟", global); 8 | // } 9 | // dweb(); 10 | 11 | // ✨ ① 첫번째 방법 12 | let global = "Incheon"; 13 | function chunkNamespace() { 14 | // Chunk of code goes here 15 | // Any variables defined in the chunk are local to thisfunction 16 | // instead of cluttering up the global namespace. 17 | 18 | let global = "Dweb"; // 🌟 주석달면 "incheon" 19 | function dweb() { 20 | console.log("🌟", global); 21 | } 22 | dweb(); 23 | } 24 | chunkNamespace(); // 🚨 But don't forget to invoke the function! 25 | 26 | // ✨ ② 두번째 방법. 간단하게 anonymous function을 정의한 뒤 호출해도 됨 27 | (function () { 28 | // chunkNamespace() function rewritten as an unnamed expression. 29 | // Chunk of code goes here 30 | 31 | let global = "Dweb"; // 🌟 주석달면 "incheon" 32 | function dweb() { 33 | console.log("🌟", global); 34 | } 35 | dweb(); 36 | })(); // End the function literal and invoke it now. 37 | -------------------------------------------------------------------------------- /8-Functions/app2.js: -------------------------------------------------------------------------------- 1 | // 🌟 8.1.2. Function Expressions 2 | // This function expression defines a function that squares its argument. 3 | // Note that we assign it to a variable 4 | 5 | const square = function (x) { 6 | return x * x; 7 | }; 8 | 9 | // Function expressions can include names, which is useful for recursion. 10 | const f = function fact(x) { 11 | if (x <= 1) return 1; 12 | else return x * fact(x - 1); 13 | }; 14 | 15 | // Function expressions can also be used as arguments to other functions: 16 | [3, 2, 1].sort(function (a, b) { 17 | return a - b; 18 | }); 19 | 20 | // Function expressions are sometimes defined and immediately invoked: 21 | let tensquared = (function (x) { 22 | return x * x; 23 | })(10); 24 | -------------------------------------------------------------------------------- /8-Functions/app20.js: -------------------------------------------------------------------------------- 1 | // 🌟 Closures 2 | // ✨ Nested functions 에서의 lexical scoping rules을 이해할 것 3 | 4 | // 🔥 매우 쉬운 예제 5 | // → checkscope() 함수는 local variable 을 선언하고 있으며, 6 | // → checkscope() 함수는 local variable의 값을 반환하는 함수를 정의하고, 호출하고 있음 7 | // 당연히, checkscope()을 invoke할 때 local variable 이 반환될 것 8 | 9 | let scope = "global scope"; // A global variable 10 | function checkscope() { 11 | let scope = "local scope"; // A local variable 12 | function f() { 13 | return scope; // Return the value in scope here 14 | } 15 | return f(); 16 | } 17 | checkscope(); // => "local scope" 18 | -------------------------------------------------------------------------------- /8-Functions/app21.js: -------------------------------------------------------------------------------- 1 | // 🌟 Closures 2 | // ✨ Nested functions 에서의 lexical scoping rules을 이해할 것 3 | 4 | // 🔥 예제) 이전 예제와는 달리 안쪽에 있던 () 가 외부에 놓임. 즉, "nested function"를 반환함 5 | // 🙋 외부에서 nested function이 호출되면 어떤 일이 발생하는가? 6 | 7 | let scope = "global scope"; // A global variable 8 | 9 | function checkscope() { 10 | let scope = "local scope"; // A local variable 11 | function f() { 12 | return scope; // Return the value in scope here 13 | } 14 | return f; 15 | } 16 | scope = "Incheon National University"; 17 | 18 | let v = checkscope(); 19 | let s = v(); // 🙋 What does this return? 20 | -------------------------------------------------------------------------------- /8-Functions/app22.js: -------------------------------------------------------------------------------- 1 | // 🌟 Closures 2 | // ✨ Nested functions 에서의 lexical scoping rules을 이해할 것 3 | 4 | // 😯 두 가지 방식을 비교할 것 5 | 6 | // ✨ ① 방법 7 | // Initialize the counter property of the function object. 8 | // Function declarations are hoisted so we really can 9 | // do this assignment before the function declaration. 10 | uniqueInteger1.counter = 0; 11 | // This function returns a different integer each time it is called. 12 | // It uses a property of itself to remember the next value to be returned. 13 | function uniqueInteger1() { 14 | return uniqueInteger1.counter++; // Return and increment counter property 15 | } 16 | uniqueInteger1(); // => 0 17 | uniqueInteger1(); // => 1 18 | 19 | // ✨ ② 방법 20 | // uniqueInteger() function that used a property of the function itself 21 | // to keep track of the next value to be returned. 22 | 23 | let uniqueInteger2 = (function () { 24 | // Define and invoke 25 | let counter = 0; // Private state of function below 26 | return function () { 27 | return counter++; 28 | }; 29 | })(); 30 | uniqueInteger2(); // => 0 31 | uniqueInteger2(); // => 1 32 | -------------------------------------------------------------------------------- /8-Functions/app23.js: -------------------------------------------------------------------------------- 1 | // 🌟 Closures 2 | // ✨ Nested functions 에서의 lexical scoping rules을 이해할 것 3 | 4 | // 예제. 객채를 반환 5 | function counter() { 6 | let n = 0; 7 | return { 8 | count: function () { 9 | return n++; 10 | }, 11 | reset: function () { 12 | n = 0; 13 | }, 14 | }; 15 | } 16 | 17 | let c = counter(), 18 | d = counter(); // Create two counters 19 | 20 | console.log(c.count()); // => 0 21 | console.log(d.count()); // => 0: they count independently 22 | c.reset(); // reset() and count() methods share state 23 | console.log(c.count()); // => 0: because we reset c 24 | console.log(d.count()); // => 1: d was not reset 25 | -------------------------------------------------------------------------------- /8-Functions/app24.js: -------------------------------------------------------------------------------- 1 | // 🌟 Closures 2 | // ✨ Nested functions 에서의 lexical scoping rules을 이해할 것 3 | 4 | // 예제. 객체를 반환 5 | // local variable을 선언하지 않는 대신 Private state로 함수 인자 n을 사용 6 | function counter(n) { 7 | // Function argument n is the private variable 8 | return { 9 | // Property getter method returns and increments private counter var. 10 | get count() { 11 | return n++; 12 | }, 13 | // Property setter doesn't allow the value of n to decrease 14 | set count(m) { 15 | if (m > n) n = m; 16 | else throw Error("count can only be set to a larger value"); 17 | }, 18 | }; 19 | } 20 | 21 | let c = counter(1000); 22 | c.count; // => 1000 23 | c.count; // => 1001 24 | c.count = 2000; 25 | c.count; // => 2000 26 | //c.count = 2000; // !Error: count can only be set to a larger value 27 | -------------------------------------------------------------------------------- /8-Functions/app25.js: -------------------------------------------------------------------------------- 1 | // 🌟 Closures 2 | // ✨ Nested functions 에서의 lexical scoping rules을 이해할 것 3 | // 🚨 예제 1 4 | // This function returns a function that always returns v 5 | 6 | function constfunc(v) { 7 | return () => v; 8 | } 9 | // Create an array of constant functions: 10 | let funcs1 = []; 11 | for (var i = 0; i < 10; i++) funcs1[i] = constfunc(i); 12 | // The function at array element 5 returns the value 5. 13 | funcs1[5](); // => 5 14 | 15 | // 🚨 예제 2 16 | // Return an array of functions that return the values 0-9 17 | function constfuncs() { 18 | let funcs2 = []; 19 | for (var i = 0; i < 10; i++) { 20 | funcs2[i] = () => i; 21 | } 22 | return funcs2; 23 | } 24 | 25 | let funcs2 = constfuncs(); 26 | funcs2[5](); // => 10; Why doesn't this return 5? 27 | -------------------------------------------------------------------------------- /8-Functions/app26.js: -------------------------------------------------------------------------------- 1 | // 🌟 8.7 Function Properties, Methods, and Constructor 2 | 3 | // length proerty indicates the number of parameters expected by the function. 4 | function func1() {} 5 | 6 | function func2(a, b) {} 7 | 8 | console.log(func1.length, func1.name); 9 | // Expected output: 0 10 | 11 | console.log(func2.length, func2.name); 12 | // Expected output: 2 13 | -------------------------------------------------------------------------------- /8-Functions/app27.js: -------------------------------------------------------------------------------- 1 | // 🌟 8.7 Function Properties, Methods, and Constructor 2 | 3 | // ① call() 메서드 사용하는 첫번째 예제 4 | let obj = { class: "dweb", prof: "giseok" }; 5 | 6 | // ✨ 여기서 this는 call() 메서드가 호출될 때 결정됨 7 | let fullname = function (name) { 8 | this.class = "incheon" + this.class; 9 | this.prof = this.prof + name; 10 | console.log(name); 11 | }; 12 | // 🔥 fullname 함수가 obj의 메서드인 것 마냥 indirectly 호출됨 13 | fullname.call(obj, "park"); 14 | 15 | // ② call() 메서드 사용하는 두번째 예제 16 | let greetings = [ 17 | { greeting: "Incheon", name: "횃불이" }, 18 | { greeting: "Songdo", name: "유니" }, 19 | ]; 20 | 21 | for (var i = 0; i < greetings.length; i++) { 22 | (function (i) { 23 | // console.log(this); 24 | // 여기서 this는 call에 전달되는 객체 { greeting: "...", name: "..." } 25 | // this 객체에 print 메서드를 만들어 호출하는 것 26 | this.print = function () { 27 | console.log("#" + i + " " + this.greeting + ", " + this.name); 28 | }; 29 | this.print(); 30 | }).call(greetings[i], i); 31 | } 32 | -------------------------------------------------------------------------------- /8-Functions/app28.js: -------------------------------------------------------------------------------- 1 | // 🌟 8.7 Function Properties, Methods, and Constructor 2 | 3 | // ✨ 예제 ① 4 | // This function needs to be bound 5 | let f = (y) => { 6 | return this.x + y; 7 | }; 8 | 9 | let o = { x: 1 }; // An object we'll bind to 10 | let g = f.bind(o); // Calling g(x) invokes f() on o 11 | g(2); // => 3 12 | // 안바뀜 13 | let p = { x: 10, g }; // Invoke g() as a method of this object 14 | p.g(2); // => 3: g is still bound to o, not p. 15 | 16 | // ✨ 예제 ② 17 | let sum = (x, y) => x + y; // Return the sum of 2 args 18 | let succ = sum.bind(null, 1); // Bind the first argument to 1 19 | succ(2); //=>3:xisboundto1,andwepass2forthey argument 20 | function f(y, z) { 21 | return this.x + y + z; 22 | } 23 | let g1 = f.bind({ x: 1 }, 2); // Bind this and y 24 | g1(3); // => 6: this.x is bound to 1, y is bound to 2 and z is 3 25 | -------------------------------------------------------------------------------- /8-Functions/app29.js: -------------------------------------------------------------------------------- 1 | // 🌟 8.7 Function Properties, Methods, and Constructor 2 | 3 | const f = new Function("x", "y", "return x*y;"); 4 | console.log(f(10, 10)); 5 | 6 | // 🔥🔥 The function it creates do not use lexical scoping 7 | let scope = "global"; 8 | function constructFunction() { 9 | let scope = "local"; 10 | console.log("😯", scope); 11 | return new Function("return scope"); 12 | // Doesn't capture local scope! 13 | } 14 | // This line returns "global" because the function returned by the 15 | // Function() constructor does not use the local scope. 16 | console.log(constructFunction()()); // => "global" 17 | 18 | scope = "incheon"; 19 | console.log(constructFunction()()); // => "incheon" 20 | -------------------------------------------------------------------------------- /8-Functions/app3.js: -------------------------------------------------------------------------------- 1 | // 🌟 8.1.3. arrow functions 2 | 3 | const sum1 = (x, y) => { 4 | return x + y; 5 | }; 6 | // return 키워드 생략할 때, 7 | const sum2 = (x, y) => x + y; 8 | 9 | const polynomial = (x) => x * x + 2 * x + 3; 10 | const constantFunc = () => 42; 11 | 12 | //Good:f() returns an object 13 | const f = (x) => { 14 | return { value: x }; 15 | }; 16 | 17 | const g = (x) => ({ value: x }); // returns an object 18 | const h = (x) => { 19 | value: x; 20 | }; // nothing 21 | 22 | // const i = x => { v: x, w: x }; // Error 23 | 24 | // Make a copy of an array with null elements removed. 25 | let filtered = [1, null, 2, 3].filter((x) => x !== null); //filtered == [1, 2, 3]; 26 | // Square some numbers: 27 | let squares = [1, 2, 3, 4].map((x) => x * x); // squares == [1,4,9,16] 28 | -------------------------------------------------------------------------------- /8-Functions/app30.js: -------------------------------------------------------------------------------- 1 | // 🌟 8.8 Functional Programming 2 | // 8.8.1 Processing Arrays with Functions 3 | 4 | let data = [1, 1, 3, 5, 5]; // This is our array of numbers 5 | 6 | // The mean is the sum of the elements divided by the number of elements 7 | let total = 0; 8 | for (let i = 0; i < data.length; i++) total += data[i]; 9 | let mean = total / data.length; // mean == 3; The mean of our data is 3 10 | // To compute the standard deviation, we first sum the squares of 11 | // the deviation of each element from the mean. 12 | total = 0; 13 | for (let i = 0; i < data.length; i++) { 14 | let deviation = data[i] - mean; 15 | total += deviation * deviation; 16 | } 17 | let stddev = Math.sqrt(total / (data.length - 1)); // stddev == 2 18 | -------------------------------------------------------------------------------- /8-Functions/app31.js: -------------------------------------------------------------------------------- 1 | // 🌟 8.8 Functional Programming 2 | // 8.8.1 Processing Arrays with Functions 3 | 4 | // First, define two simple functions 5 | const sum = (x, y) => x + y; 6 | const square = (x) => x * x; 7 | 8 | // Then use those functions with Array methods to compute mean and stddev 9 | let data = [1, 1, 3, 5, 5]; 10 | let mean = data.reduce(sum) / data.length; // mean == 3 let deviations = data.map(x => x-mean); 11 | let stddev = Math.sqrt(deviations.map(square).reduce(sum) / (data.length - 1)); 12 | stddev; // => 2 13 | -------------------------------------------------------------------------------- /8-Functions/app32.js: -------------------------------------------------------------------------------- 1 | // 🌟 8.8 Functional Programming 2 | // 8.8.1 Processing Arrays with Functions 3 | 4 | const map = function (a, ...args) { 5 | return a.map(...args); //배열 반환 6 | }; 7 | const reduce = function (a, ...args) { 8 | return a.reduce(...args); // number 반환 9 | }; 10 | 11 | const sum = (x, y) => x + y; 12 | const square = (x) => x * x; 13 | 14 | let data = [1, 1, 3, 5, 5]; 15 | let mean = reduce(data, sum) / data.length; 16 | let deviations = map(data, (x) => x - mean); 17 | let stddev = Math.sqrt( 18 | reduce(map(deviations, square), sum) / (data.length - 1) 19 | ); 20 | stddev; // => 2 21 | -------------------------------------------------------------------------------- /8-Functions/app33.js: -------------------------------------------------------------------------------- 1 | // 🌟 8.8 Functional Programming 2 | // 8.8.2 Higher-Order Functions 3 | 4 | // This higher-order function returns a new function that passes its 5 | // arguments to f and returns the logical negation of f's return value; 6 | function not(f) { 7 | return function (...args) { 8 | // Return a new function 9 | let result = f.apply(this, args); // that calls f 10 | return !result; // and negates its result. 11 | }; 12 | } 13 | 14 | const even = (x) => x % 2 === 0; // A function to determine if a number is even 15 | const odd = not(even); // A new function that does the opposite 16 | [1, 1, 3, 5, 5].every(odd); // => true: every element of the array is odd 17 | 18 | // Return a function that expects an array argument and applies f to 19 | // each element, returning the array of return values. 20 | // Contrast this with the map() function from earlier. 21 | const map = function (a, ...args) { 22 | return a.map(...args); //배열 반환 23 | }; 24 | function mapper(f) { 25 | return (a) => map(a, f); 26 | } 27 | 28 | const increment = (x) => x + 1; 29 | const incrementAll = mapper(increment); 30 | incrementAll([1, 2, 3]); // => [2,3,4] 31 | 32 | // Return a new function that computes f(g(...)). 33 | // The returned function h passes all of its arguments to g, then passes 34 | // the return value of g to f, then returns the return value of f. 35 | // Both f and g are invoked with the same this value as h was invoked with. 36 | function compose(f, g) { 37 | return function (...args) { 38 | // We use call for f because we're passing a single value and 39 | // apply for g because we're passing an array of values. 40 | return f.call(this, g.apply(this, args)); 41 | }; 42 | } 43 | const sum = (x, y) => x + y; 44 | const square = (x) => x * x; 45 | compose(square, sum)(2, 3); // => 25; the square of the sum 46 | -------------------------------------------------------------------------------- /8-Functions/app4.js: -------------------------------------------------------------------------------- 1 | // 🌟 8.1.4. Nested Functions 2 | 3 | // console.log(hypotenuse(3, 4)); // Hoisting 4 | 5 | let s1 = hypotenuse(10, 20); 6 | 7 | function hypotenuse(a, b) { 8 | function square(x) { 9 | return x * x + a * b; 10 | } 11 | return square; 12 | // return Math.sqrt(square(a) + square(b)); 13 | } 14 | 15 | let s2 = hypotenuse(5, 5); 16 | 17 | console.log(s1(10)); 18 | console.log(s2(2)); 19 | -------------------------------------------------------------------------------- /8-Functions/app5.js: -------------------------------------------------------------------------------- 1 | // 🌟 8.2.2 Method Invocation 2 | 3 | let calculator = { 4 | // An object literal 5 | operand1: 1, 6 | operand2: 1, 7 | add() { 8 | // We're using method shorthand syntax for this function 9 | // Note the use of the this keyword to refer to the containing object. 10 | this.result = this.operand1 + this.operand2; 11 | }, 12 | }; 13 | 14 | calculator.add(); // A method invocation to compute 1+1. 15 | calculator.result; // => 2 16 | -------------------------------------------------------------------------------- /8-Functions/app6.js: -------------------------------------------------------------------------------- 1 | // 🌟 8.2.2 Method Invocation 2 | "use strict"; 3 | let o = { 4 | // An object o. 5 | m: function () { 6 | // Method m of the object. 7 | let self = this; // Save the "this" value in a variable. 8 | this === o; // => true: "this" is the object o. 9 | console.log(`😃 ${this === o}`); 10 | 11 | f(); // Now call the helper function f(). ✨ Hoisting 12 | 13 | function f() { 14 | // A nested function f 15 | this === o; // => false: "this" is global or ✨ undefined 16 | console.log(`🌟 ${this === o}`); 17 | 18 | self === o; // => true: self is the outer "this" value. 19 | console.log(`✨ ${self === o}`); 20 | } 21 | }, 22 | }; 23 | o.m(); // Invoke the method m on the object o. 24 | -------------------------------------------------------------------------------- /8-Functions/app7.js: -------------------------------------------------------------------------------- 1 | // 🌟 8.2.2 Method Invocation 2 | "use strict"; 3 | let o = { 4 | // An object o. 5 | m: function () { 6 | console.log(`😃 ${this === o}`); 7 | const f = () => { 8 | this === o; // true, since arrow functions inherit this 9 | console.log(`🌟 ${this === o}`); 10 | }; 11 | f(); // Now call the helper function f(). 12 | }, 13 | }; 14 | o.m(); 15 | -------------------------------------------------------------------------------- /8-Functions/app8.js: -------------------------------------------------------------------------------- 1 | // 🌟 8.2.2 Method Invocation 2 | 3 | "use strict"; 4 | let o = { 5 | // An object o. 6 | m: function () { 7 | console.log(`😃 ${this === o}`); 8 | const f = function () { 9 | // true, 🌟 since we bound this function to the outer this 10 | console.log(`👏 ${this === o}`); 11 | }.bind(this); 12 | f(); 13 | }, 14 | }; 15 | o.m(); 16 | 17 | // 😀 bind() 메서드 예제: bind 메서드의 argument 에 객체를 넣을 수 있음 18 | let k = function (a) { 19 | return this.x + a; 20 | }; 21 | let k_bind = k.bind({ x: 10, y: 20 }); 22 | console.log(`👏`, k_bind(5)); 23 | -------------------------------------------------------------------------------- /8-Functions/app9.js: -------------------------------------------------------------------------------- 1 | // 🌟 8.3.1 Optional Parameters and Defaults 2 | "use strict"; 3 | 4 | // Append the names of the enumerable properties of object o to the 5 | // array a, and return a. If a is omitted, create and return a new array. 6 | function getPropertyNames(o, a) { 7 | if (a === undefined) a = []; // If undefined, use a new array 8 | for (let property in o) a.push(property); 9 | return a; 10 | } 11 | 12 | // getPropertyNames() can be invoked with one or two arguments: 13 | let o = { x: 1 }, 14 | p = { y: 2, z: 3 }; //Two objects for testing 15 | let a = getPropertyNames(o); // a == ["x"]; get o's properties in a new array 16 | console.log(`before`, a); 17 | getPropertyNames(p, a); // a == ["x","y","z"]; add p's properties to it 18 | console.log(`after`, a); 19 | -------------------------------------------------------------------------------- /8-Functions/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ✨✨ Chapter 8. Functions 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /9-Classes/app1.js: -------------------------------------------------------------------------------- 1 | // 🌟 Classes and Prototypes 2 | 3 | // 예제. 4 | // This is a factory function that returns a new range object. 5 | function range(from, to) { 6 | // Use Object.create() to create an object that inherits from the 7 | // prototype object defined below. The prototype object is stored as 8 | // a property of this function, and defines the shared methods (behavior) 9 | // for all range objects. 10 | let r = Object.create(range.methods); 11 | // Store the start and end points (state) of this new range object. 12 | // These are noninherited properties that are unique to this object. 13 | r.from = from; 14 | r.to = to; 15 | // Finally return the new object 16 | return r; 17 | } 18 | // This prototype object defines methods inherited by all range objects. 19 | range.methods = { 20 | // Return true if x is in the range, false otherwise 21 | // This method works for textual and Date ranges as well asnumeric. 22 | includes(x) { 23 | return this.from <= x && x <= this.to; 24 | }, 25 | // A generator function that makes instances of the class iterable. 26 | // Note that it only works for numeric ranges. 27 | *[Symbol.iterator]() { 28 | for (let x = Math.ceil(this.from); x <= this.to; x++) yield x; 29 | }, 30 | // Return a string representation of the range 31 | toString() { 32 | return "(" + this.from + "..." + this.to + ")"; 33 | }, 34 | }; 35 | 36 | // Here are example uses of a range object. 37 | let r = range(1, 3); // Create a range object 38 | r.includes(2); // => true: 2 is in the range 39 | r.toString(); // => "(1...3)" 40 | [...r]; // => [1, 2, 3]; convert to an array via iterator 41 | console.log(r); 42 | -------------------------------------------------------------------------------- /9-Classes/app2.js: -------------------------------------------------------------------------------- 1 | // 🌟 Classes and Constructors 2 | 3 | // 예제 4 | // This is a constructor function that initializes new Range objects. 5 | // Note that it does not create or return the object. It just initializes this. 6 | function Range(from, to) { 7 | // Store the start and end points (state) of this new range object. 8 | // These are noninherited properties that are unique to this object. 9 | this.from = from; 10 | this.to = to; 11 | } 12 | 13 | // All Range objects inherit from this object. 14 | // Note that the property name must be "prototype" for this to work. 15 | Range.prototype = { 16 | // Explicitly set the constructor back-reference 17 | constructor: Range, 18 | // Return true if x is in the range, false otherwise 19 | // This method works for textual and Date ranges as well as numeric. 20 | includes: function (x) { 21 | return this.from <= x && x <= this.to; 22 | }, 23 | // A generator function that makes instances of the class iterable. 24 | // Note that it only works for numeric ranges. 25 | [Symbol.iterator]: function* () { 26 | for (let x = Math.ceil(this.from); x <= this.to; x++) yield x; 27 | }, 28 | // Return a string representation of the range 29 | toString: function () { 30 | return "(" + this.from + "..." + this.to + ")"; 31 | }, 32 | }; 33 | 34 | // Here are example uses of this new Range class 35 | let r = new Range(1, 3); // Create a Range object; note the use of new 36 | r.includes(2); // => true: 2 is in the range 37 | r.toString(); // => "(1...3)" 38 | [...r]; // => [1, 2, 3]; convert to an array via iterator 39 | 40 | // ✨ constructor는 생략 가능한 프로퍼티 41 | console.log("🌟", Range.prototype.constructor === Range); 42 | 43 | // ✨ 정의된 클래스에 메서드를 하나씩 추가할 수 있음 44 | Range.prototype.dweb = function (x) { 45 | return this.from <= x && x <= this.to; 46 | }; 47 | Range.prototype.incheon = function () { 48 | return "(" + this.from + "..." + this.to + ")"; 49 | }; 50 | -------------------------------------------------------------------------------- /9-Classes/app3.js: -------------------------------------------------------------------------------- 1 | // 🌟 Constructor Property 2 | 3 | let F = function () { 4 | this.x = "Dweb"; 5 | this.y = "I really love Incheon"; 6 | }; // This is a function object. 7 | 8 | console.log(typeof F); 9 | let p = F.prototype; // This is the prototype object associated with F. 10 | let c = p.constructor; // This is the function associated with the prototype. 11 | c === F; // => true: F.prototype.constructor === F for any F 12 | 13 | let o = new F(); // Create an object o of class F 14 | console.log(typeof o); 15 | o.constructor === F; // => true: the constructor property specifies the class 16 | -------------------------------------------------------------------------------- /9-Classes/app4.js: -------------------------------------------------------------------------------- 1 | // 🌟 Classes with the class Keyword 2 | 3 | class Range { 4 | constructor(from, to) { 5 | // Store the start and end points (state) of this new range object. 6 | // These are noninherited properties that are unique to this object. 7 | this.from = from; 8 | this.to = to; 9 | } 10 | 11 | // Return true if x is in the range, false otherwise 12 | // This method works for textual and Date ranges as well as numeric. 13 | includes(x) { 14 | return this.from <= x && x <= this.to; 15 | } 16 | 17 | // A generator function that makes instances of the class iterable. 18 | // Note that it only works for numeric ranges. 19 | *[Symbol.iterator]() { 20 | for (let x = Math.ceil(this.from); x <= this.to; x++) yield x; 21 | } 22 | 23 | // Return a string representation of the range 24 | toString() { 25 | return `(${this.from}...${this.to})`; 26 | } 27 | } 28 | 29 | // Here are example uses of this new Range class 30 | let r = new Range(1, 3); // Create a Range object 31 | r.includes(2); // => true: 2 is in the range 32 | r.toString(); // => "(1...3)" 33 | [...r]; // => [1, 2, 3]; convert to an array via iterator 34 | -------------------------------------------------------------------------------- /9-Classes/app5.js: -------------------------------------------------------------------------------- 1 | // 🌟 Classes with the class Keyword 2 | 3 | class Range { 4 | constructor(from, to) { 5 | // Store the start and end points (state) of this new range object. 6 | // These are noninherited properties that are unique to this object. 7 | this.from = from; 8 | this.to = to; 9 | } 10 | 11 | // Return true if x is in the range, false otherwise 12 | // This method works for textual and Date ranges as well as numeric. 13 | includes(x) { 14 | return this.from <= x && x <= this.to; 15 | } 16 | 17 | // A generator function that makes instances of the class iterable. 18 | // Note that it only works for numeric ranges. 19 | *[Symbol.iterator]() { 20 | for (let x = Math.ceil(this.from); x <= this.to; x++) yield x; 21 | } 22 | 23 | // Return a string representation of the range 24 | toString() { 25 | return `(${this.from}...${this.to})`; 26 | } 27 | } 28 | 29 | // A Span is like a Range, but instead of initializing it with 30 | // a start and an end, we initialize it with a start and a length 31 | class Span extends Range { 32 | constructor(start, length) { 33 | if (length >= 0) { 34 | super(start, start + length); 35 | } else { 36 | super(start + length, start); 37 | } 38 | } 39 | } 40 | 41 | let s = new Span(1, 3); 42 | -------------------------------------------------------------------------------- /9-Classes/app6.js: -------------------------------------------------------------------------------- 1 | // 🌟 Classes with the class Keyword 2 | 3 | // 아래 두 케이스를 비교 4 | // 1. 변수에 함수 할당 5 | let square = function (x) { 6 | return x * x; 7 | }; 8 | square(3); // => 9 9 | 10 | // 2. 변수에 클래스 할당 11 | let Square = class { 12 | constructor(x) { 13 | this.area = x * x; 14 | } 15 | includes() { 16 | return this.area * this.area; 17 | } 18 | }; 19 | new Square(3).area; // => 9 20 | new Square(3).includes(); // ==> 81 21 | -------------------------------------------------------------------------------- /9-Classes/app7.js: -------------------------------------------------------------------------------- 1 | // 🌟 Classes with the class Keyword 2 | 3 | class Range { 4 | constructor(from, to) { 5 | // Store the start and end points (state) of this new range object. 6 | // These are noninherited properties that are unique to this object. 7 | this.from = from; 8 | this.to = to; 9 | } 10 | 11 | // Return true if x is in the range, false otherwise 12 | // This method works for textual and Date ranges as well as numeric. 13 | includes(x) { 14 | return this.from <= x && x <= this.to; 15 | } 16 | 17 | // A generator function that makes instances of the class iterable. 18 | // Note that it only works for numeric ranges. 19 | *[Symbol.iterator]() { 20 | for (let x = Math.ceil(this.from); x <= this.to; x++) yield x; 21 | } 22 | 23 | // Return a string representation of the range 24 | toString() { 25 | return `(${this.from}...${this.to})`; 26 | } 27 | 28 | static parse(s) { 29 | let matches = s.match(/^\((\d+)\.\.\.(\d+)\)$/); 30 | if (!matches) { 31 | throw new TypeError(`Cannot parse Range from "${s}".`); 32 | } 33 | return new Range(parseInt(matches[1]), parseInt(matches[2])); 34 | } 35 | } 36 | 37 | let r = Range.parse("(1...10)"); // Returns a new Range object 38 | //r.parse("(1...10)"); // TypeError: r.parse is not a function 39 | -------------------------------------------------------------------------------- /9-Classes/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ✨✨ Chapter 9. Classes 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Appendix-React/app.js: -------------------------------------------------------------------------------- 1 | function MyApp() { 2 | return

    Hello, world!

    ; 3 | } 4 | 5 | const container = document.getElementById("root"); 6 | const root = ReactDOM.createRoot(container); 7 | root.render(); 8 | -------------------------------------------------------------------------------- /Appendix-React/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello World 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
    14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Appendix-TypeScript/app1.js: -------------------------------------------------------------------------------- 1 | // 🌟 We cannot understand how it works exactly with only function signature. 2 | // ⛔️ try and see if you can figure out how they work 3 | 4 | function add(num1, num2, num3) { 5 | res = num1 + num2 + num3; 6 | return res; 7 | } 8 | 9 | function showNames(students) { 10 | const inu_students = students.map((student) => student + " 💕 inu"); 11 | return inu_students; 12 | } 13 | 14 | const sum = add("Incheon", " National", " University"); 15 | console.log(sum); 16 | 17 | add(1, 2, 3); 18 | 19 | const students = ["kim", "Lee", "Park", "Choi"]; 20 | const inu_students = showNames(students); 21 | console.log(inu_students); 22 | -------------------------------------------------------------------------------- /Appendix-TypeScript/app2.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | function add(num1, num2, num3) { 3 | let res = num1 + num2 + num3; 4 | return res; 5 | } 6 | function showNames(students) { 7 | const inu_students = students.map((student) => student + " 💕 inu"); 8 | return inu_students; 9 | } 10 | -------------------------------------------------------------------------------- /Appendix-TypeScript/app2.ts: -------------------------------------------------------------------------------- 1 | function add(num1: number, num2: number, num3: number): number { 2 | let res = num1 + num2 + num3; 3 | return res; 4 | } 5 | 6 | function showNames(students: string[]): string[] { 7 | const inu_students = students.map((student) => student + " 💕 inu"); 8 | return inu_students; 9 | } 10 | -------------------------------------------------------------------------------- /Appendix-TypeScript/app3.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | class UserAccount { 3 | constructor(name, id) { 4 | this.name = name; 5 | this.id = id; 6 | } 7 | } 8 | const student = new UserAccount("incheon", 1); 9 | -------------------------------------------------------------------------------- /Appendix-TypeScript/app3.ts: -------------------------------------------------------------------------------- 1 | interface User { 2 | name: string; 3 | id: number; 4 | } 5 | class UserAccount { 6 | name; 7 | id; 8 | constructor(name: string, id: number) { 9 | this.name = name; 10 | this.id = id; 11 | } 12 | } 13 | const student: User = new UserAccount("incheon", 1); 14 | -------------------------------------------------------------------------------- /Appendix-TypeScript/app4.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | function generics1(arg) { 3 | return arg; 4 | } 5 | function generics2(arg) { 6 | return arg; 7 | } 8 | function generics3(arg) { 9 | return arg; 10 | } 11 | function generics4(arg) { 12 | console.log(arg.length); // array .length property 13 | return arg; 14 | } 15 | const inu = generics4(["a", "b", "c"]); 16 | -------------------------------------------------------------------------------- /Appendix-TypeScript/app4.ts: -------------------------------------------------------------------------------- 1 | function generics1(arg: number): number { 2 | return arg; 3 | } 4 | 5 | function generics2(arg: string): string { 6 | return arg; 7 | } 8 | 9 | function generics3(arg: Type): Type { 10 | return arg; 11 | } 12 | 13 | function generics4(arg: Type[]): Type[] { 14 | console.log(arg.length); // array .length property 15 | return arg; 16 | } 17 | 18 | const inu = generics4(["a", "b", "c"]); 19 | -------------------------------------------------------------------------------- /Appendix-TypeScript/greeter.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | function greeter(person) { 3 | return "Hello, " + person; 4 | } 5 | let user = "💕 Incheon"; 6 | document.body.textContent = greeter(user); 7 | -------------------------------------------------------------------------------- /Appendix-TypeScript/greeter.ts: -------------------------------------------------------------------------------- 1 | function greeter(person: string) { 2 | return "Hello, " + person; 3 | } 4 | 5 | let user: string = "💕 Incheon"; 6 | 7 | document.body.textContent = greeter(user); 8 | -------------------------------------------------------------------------------- /Appendix-TypeScript/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 🌟 TypeScript 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

    2 | 3 | #### Dweb ❌ Incheon National University (INU) 4 | 5 | ## 🌟 JavaScript in Web 6 | 7 | ⚠️ Copyright © 2024. _Dweb_ All Rights Reserved. 8 | 9 |

    10 | -------------------------------------------------------------------------------- /images/Dweb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dweb-Incheon/JS/9a06f1954fc98bf813480101f372a91b6d81d660/images/Dweb.png -------------------------------------------------------------------------------- /images/INU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dweb-Incheon/JS/9a06f1954fc98bf813480101f372a91b6d81d660/images/INU.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dweb", 3 | "version": "1.0.0", 4 | "description": "dweb web programming class", 5 | "main": "index.js", 6 | "type": "commonjs", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/Dweb-Incheon/JavaScript.git" 13 | }, 14 | "keywords": [ 15 | "javascript" 16 | ], 17 | "author": "giseok", 18 | "license": "ISC", 19 | "bugs": { 20 | "url": "https://github.com/Dweb-Incheon/JavaScript/issues" 21 | }, 22 | "homepage": "https://github.com/Dweb-Incheon/JavaScript#readme", 23 | "dependencies": { 24 | "http": "^0.0.1-security", 25 | "json-server": "^0.17.4", 26 | "node-fetch": "^3.3.2", 27 | "react": "^18.3.1", 28 | "react-dom": "^18.3.1", 29 | "ws": "^8.17.0" 30 | }, 31 | "devDependencies": { 32 | "webpack": "^5.91.0", 33 | "webpack-cli": "^5.1.4" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "target": "ES6", 5 | "module": "commonjs" 6 | } 7 | } 8 | --------------------------------------------------------------------------------