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