├── .gitignore ├── 01) 4. 변수 & 5. 표현식과 문 ├── June.md ├── Pposong.md ├── README.md ├── choonsik.md ├── dana.md └── saint.md ├── 02) 6. 데이터 타입 & 7. 연산자 ├── June.md ├── Pposong.md ├── README.md ├── choonsik.md ├── dana.md └── saint.md ├── 03) 8. 제어문 & 9. 타입변환과 단축평가 ├── 8_1.png ├── 8_2.png ├── Dana.md ├── June.md ├── README.md ├── ayaan.md ├── choonsik.md └── saint.md ├── 04) 10. 객체 리터럴 & 11. 원시값과 객체의 비교 ├── Dana.md ├── June.md ├── README.md ├── ayaan.md ├── choonsik.md └── saint.md ├── 05) 12. 함수 ├── Ayaan.md ├── Dana.md ├── June.md ├── Pposong.md ├── README.md ├── choonsik.md └── saint.md ├── 06) 23. 실행컨텍스트 & 13. 스코프 ├── Ayaan.md ├── Dana.md ├── DanaImgs │ ├── IMG_0996044C3E28-1.jpeg │ ├── IMG_21F6C19D6637-1.jpeg │ ├── IMG_5B20F389C697-1.jpeg │ ├── IMG_DEFDBAC3D287-1.jpeg │ ├── Untitled 1.png │ ├── Untitled 10.png │ ├── Untitled 11.png │ ├── Untitled 12.png │ ├── Untitled 13.png │ ├── Untitled 14.png │ ├── Untitled 15.png │ ├── Untitled 16.png │ ├── Untitled 17.png │ ├── Untitled 18.png │ ├── Untitled 2.png │ ├── Untitled 3.png │ ├── Untitled 4.png │ ├── Untitled 5.png │ ├── Untitled 6.png │ ├── Untitled 7.png │ ├── Untitled 8.png │ ├── Untitled 9.png │ ├── Untitled.png │ └── 프로젝트_아이디어-4.jpg ├── June.md ├── README.md ├── choonsik.md └── saint.md ├── 07) 14. 전역변수의 문제점 & 15. let, const와 블록 레벨 스코프 ├── June.md ├── README.md ├── choonsik.md ├── dana.md └── saint.md ├── 08) 16. 프로퍼티 어트리뷰트 & 17. 생성자 함수에 의한 객체 생성 ├── June.md ├── README.md ├── choonsik.md ├── dana.md └── saint.md ├── 09) 18. 함수와 일급객체 ├── June.md ├── README.md ├── choonsik.md ├── dana.md └── saint.md ├── 10) 19. 프로토타입 ├── June.md ├── README.md ├── choonsik.md ├── dana(1).md └── saint.md ├── 11) 20. strict mode & 21. 빌트인 객체 & 22. this ├── June.md ├── JuneImage │ └── rapper.jpeg ├── README.md ├── choonti.md └── dana.md ├── 12) 24. 클로저 ├── Dana.md ├── June.md ├── README.md └── choonti.md ├── 13) 25. 클래스 ├── Dana.md ├── June.md ├── README.md └── choonsik.md ├── 14) 26. 함수의 추가 기능 ├── Dana.md ├── June.md ├── README.md └── choonsik.md ├── 15) 27. 배열 ├── June.md ├── README.md └── choonsik.md ├── 16) 28. Number & 29. Math & 30. Date & 31. RegExp ├── June.md ├── README.md └── choonsik.md ├── 17) 32. String & 33. Symbol ├── June.md ├── JuneImage │ ├── 1.png │ ├── 2.png │ ├── 3.png │ └── 4.png ├── Pposong.md ├── README.md ├── choonsik.md └── dana.md ├── 18) 38. 브라우저의 렌더링 과정 ├── June.md ├── README.md └── choonsik.md ├── 19) 39. DOM ├── June.md ├── README.md └── choonsik.md ├── 20) 34. 이터러블 & 35. 스프레드 문법 & 36. 디스트럭쳐링 할당 ├── June.md ├── README.md └── choonsik.md ├── 21) 37. Set과 Map & 42. 비동기 프로그래밍 ├── June.md ├── README.md └── choonsik.md ├── 22) 40. 이벤트 ├── June.md ├── README.md └── choonsik.md ├── 23) 41. 타이머 & 43. Ajax ├── June.md ├── README.md └── images │ ├── 1.png │ └── 2.png ├── 24) 45. 프로미스 └── README.md ├── 25) 46. 제너레이터와 async await └── README.md ├── 26) 47. 에러 처리 & 48. 모듈 └── README.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /01) 4. 변수 & 5. 표현식과 문/June.md: -------------------------------------------------------------------------------- 1 | # 4강 변수 2 | 3 | ## 4.1 변수란 무엇인가? 왜 필요한가? 4 | 5 | 변수는 프로그래밍 언어에서 데이터를 관리하기 위한 핵심개념이다. 6 | 7 | 우리는 `10 + 20` 이라는 것을 보면 `30`이라는 것을 알지만, 컴퓨터는 `10`이라는 숫자와 `20`이라는 숫자를 알아야 하고, `+`라는 연산자도 알아야 한다. 8 | 이 모든 것을 메모리에 저장하고, CPU를 이용해 계산한다. 9 | 10 | 10 + 20의 결괏값이 30이라는 것은 메모리와 CPU를 이용해서 계산을 했다. 결괏값을 도출했다는 건 결괏값으로 무언가를 하겠다는 의미였을텐데 30이라는 값을 사용하기 위해 10 + 20의 결괏값이 저장된 메모리 공간에 직접 접근하는 것은 위험한 일이다. 11 | 12 | 그래서 **변수는 하나의 값을 저장하기 위해 확보한 메모리 공간 자체** 또는 **그 메모리 공간을 식별하기 위해 붙인 이름**을 말한다. 13 | 14 | 간단히 말해서 변수는 **값의 위치를 가리키는 상징적인 이름**이다. 15 | 16 | ```javascript 17 | // variable: 변수 이름 18 | // 30: 변수 값 19 | // "변수 이름"에 "="으로 "변수 값"을 "할당(혹은 대입, 저장)" 20 | const variable = 30; 21 | ``` 22 | 23 | 변수 이름은 개발할 때 가독성을 높이는 부수적인 효과도 있기 때문에, 변수 이름을 짓는 것에 온 힘을 다해야 한다. 24 | 25 | ## 4.2 식별자 26 | 27 | 식별자는 **어떤 값을 구별해서 식별할 수 있는 고유한 이름**을 말한다. 28 | 식별자는 어떤 값이 저장되어 있는 메모리 주소를 기억해야 한다. 그래서 식별자는 값이 아니라 메모리 주소를 저장하고 있다. 29 | 30 | 식별자는 변수, 함수, 클래스 등의 모든 이름은 전부 식별자다. 즉 메모리 상에 존재하는 어떤 값을 식별할 수 있는 이름은 모두 식별자라고 부른다. 31 | 32 | ## 4.3 변수 선언 33 | 34 | **변수를 사용하려면 반드시 선언해야 한다.** 35 | 변수를 선언할 때는 `var`, `let`, `const`와 같은 키워드를 사용할 수 있다. 36 | 37 | > `var`는 es5 키워드, `let`, `const`는 es6 키워드 38 | > `var`는 함수 레벨 스코프, `let`, `const`는 블록 레벨 스코프 39 | > `var`는 선언과 초기화가 동시에, `let`, `const`는 선언만 40 | 41 | 변수를 선언하지 않았는데 참조하려고 하면 참조 에러 (`ReferenceError`)가 발생한다. 42 | 43 | ## 4.4 변수 선언의 실행 시점과 변수 호이스팅 44 | 45 | 호이스팅은 **변수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징**을 변수 호이스팅이라고 한다. 46 | 47 | 요기서 중요한 것은 **할당**이 아닌 **선언**만 끌어올려진다는 점. 48 | 그리고 실제 코드가 끌어올려지는 것은 아니다. 49 | 50 | ## 4.5 값의 할당 51 | 52 | 변수에 값을 할당할 때는 할당 연산자 `=` 를 사용한다. 53 | 54 | ```javascript 55 | var a; // 선언 56 | a = 100; // 할당 57 | 58 | var a = 100; // 선언과 할당 동시에! 59 | ``` 60 | 61 | ```javascript 62 | console.log(a); // undefined 63 | 64 | var a = 100; // 선언은 위로 끌어올려지고, 할당은 런타임에 할당 65 | 66 | console.log(a); // 100 67 | ``` 68 | 69 | ```javascript 70 | console.log(a); // undefined 71 | 72 | a = 10; // 런타임에 할당 73 | var a; // 선언이 위로 올려짐 74 | 75 | console.log(a); // 10 76 | ``` 77 | 78 | ## 4.6 값의 재할당 79 | 80 | `var`는 재할당 할 수 있다. 사실 맨 처음에 `undefined`로 초기화되고, 값이 할당되기 때문에 이것도 재할당이라고 볼 수 있다. 81 | 82 | `const`는 재할당이 불가능하기 때문에 변수가 아닌 상수이다. 83 | 84 | `var` 변수에 값을 재할당하면 원래 있던 메모리 공간을 지우고 거기에 값을 재할당하는 것이 아니라, 새로운 메모리 공간을 만들어서 그곳으로 연결시켜준다. 이렇게 사용하지 않게 되는 메모리 공간은 가비지 컬렉터에 의해서 정리된다. 85 | 86 | # 표현식과 문 87 | 88 | ## 5.1 값 89 | 90 | **값은 식(표현식)이 평가되어 생성된 결과를 말한다.** 91 | 92 | ```javascript 93 | // 10 + 20이라는 식 94 | // 10 + 20을 평가하면 30이라는 값이 나온다. 95 | 10 + 20; 96 | ``` 97 | 98 | ## 5.2 리터럴 99 | 100 | **리터럴은 사람이 이해할 수 있는 문자 또는 약속된 기호를 사용해 값을 생성하는 표기법을 말한다.** 101 | 102 | ## 5.3 표현식 103 | 104 | **표현식은 값으로 평가될 수 있는 문이다. 즉, 표현식이 평가되면 새로운 값을 생성하거나 기존 값을 참조한다.** 105 | 106 | ## 5.4 문 107 | 108 | **문은 프로그램을 구성하는 기본 단위이자 최소 실행 단위다.** 109 | 문은 여러 토큰으로 구성된다. 110 | **토큰이란 문법적인 의미를 가지며, 문법적으로 더 이상 나눌 수 없는 코드의 기본 요소를 의미한다.** 111 | 112 | ## 5.5 세미콜론과 세미콜론 자동 삽입 기능 113 | 114 | 세미콜론(;)은 **문의 종료**를 나타낸다. 115 | 세미콜론은 생략 가능하다. 자바스크립트 엔진이 소스코드를 해석할 떄 문의 끝이라고 예측되는 지점에 세미콜론을 자동으로 붙여주는 **세미콜론 자동 삽입 기능**이 암묵적으로 수행된다. 116 | 117 | # 궁금한 것 118 | 119 | - [ ] 변수랑 식별자의 차이점은 무엇일까요 ?... 120 | -------------------------------------------------------------------------------- /01) 4. 변수 & 5. 표현식과 문/Pposong.md: -------------------------------------------------------------------------------- 1 | # 4. 변수 & 5. 표현식과 문 2 | 3 | ## 04장 변수 4 | 5 | ### 4.1 변수란 무엇인가? 왜 필요한가? 6 | 7 | 메모리 주소를 통해 값에 직접 접근하는 것은 치명적 오류를 발생시킬 가능성이 높은 매우 위험한 일이다. 8 | 9 | 만약 실수로 운영체제가 사용하고 있는 값을 변경하면 시스템을 멈추게 하는 치명적인 오류가 발생할 수도 있다. 10 | 11 | 따라서 자바스크립트는 개발자의 직접적인 메모리 제어를 허용하지 않는다. 12 | 13 | 또, 만약 자바스크립트가 개발자의 직접적인 메모리 제어를 허용하더라도 문제가 있다. 14 | 15 | 값이 저장될 메모리 주소는 코드가 실행될 때마다 임의로 결정되며, 코드가 실행되기 전에는 값이 저장된 메모리 주소를 알 수 없다. 16 | 17 | 프로그래밍 언어는 기억하고 싶은 값을 메모리에 저장하고 저장된 값을 읽어들여 재사용하기 위해 변수라는 메커니즘을 제공한다. 18 | 19 | > 변수는 하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위해 붙인 이름을 말한다. 20 | 21 | 간단히 말하자면 변수는 값을 저장하고 참조하는 메커니즘으로, **값의 위치를 가리키는 상징적인 이름**이다. 22 | 23 | 따라서 개발자가 직접 메모리 주소를 통해 값을 저장하고 참조할 필요가 없고 변수를 통해 안전하게 값에 접근할 수 있다. 24 | 25 | 메모리 공간에 저장된 값을 식별할 수 있는 고유한 이름을 **변수 이름**(또는 변수명)이라 한다. 26 | 27 | 그리고 변수에 저장된 값을 **변수 값**이라고 한다. 28 | 29 | 변수에 값을 저장하는 것을 **할당(대입, 저장)** 이라 하고, 변수에 저장된 값을 읽어들이는 것을 **참조**라 한다. 30 | 31 | ### 4.2 식별자 32 | 33 | 변수 이름을 식별자라고도 한다. 34 | 35 | > 식별자는 어떤 값을 구별해서 식별할 수 있는 고유한 이름을 말한다. 36 | 37 | 값은 메모리 공간에 저장되어 있다. 따라서 식별자는 메모리 공간에 저장되어 있는 어떤 값을 구별해서 식별해낼 수 있어야 한다. 38 | 39 | 이를 위해 식별자는 어떤 값이 저장되어 있는 메모리 주소를 기억해야 한다. 40 | 41 | 식별자라는 용어는 변수 이름에만 국한해서 사용하지 않는다. 42 | 43 | 변수, 함수, 클래스 등의 이름은 모두 식별자다. 44 | 45 | 식별자인 변수 이름으로는 메모리 상에 존재하는 변수 값을 식별할 수 있고, 함수 이름으로는 메모리 상에 존재하는 함수를 식별할 수 있다. 46 | 47 | ### 4.3 변수 선언 48 | 49 | 변수 선언이란 변수를 생성하는 것을 말한다. 50 | 51 | 좀 더 자세히 말하면 값을 저장하기 위한 메모리 공간을 확보하고 변수 이름과 확보된 메모리 공간의 주소를 연결해서 값을 저장할 수 있게 준비하는 것이다. 52 | 53 | > 변수를 사용하려면 반드시 선언이 필요하다. 변수를 선언할 때는 `var`, `let`, `const` 키워드를 사용한다. 54 | 55 | ES6에서 `let`, `const` 키워드가 도입되기 이전까지 `var` 키워드는 자바스크립트에서 변수를 선언할 수 있는 유일한 키워드였다. 56 | 57 | > var 키워드는 여러 단점이 있다. var 키워드의 여러 단점 중에서 가장 대표적인 것이 블록 레벨 스코프를 지원하지 않고 함수 레벨 스코프를 지원한다는 것이다. 이로 인해 의도치 않게 전역 변수가 선언되어 심각한 부작용이 발생하기도 한다. 58 | 59 | 자바스크립트 엔진은 변수 선언을 다음과 같은 2단계에 거쳐 수행한다. 60 | 61 | 1. 선언 단계: 변수 이름을 등록해서 자바스크립트 엔진에 변수의 존재를 알린다. 62 | 2. 초기화 단계: 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 `undefined`를 할당해 초기화한다. 63 | 64 | > 변수 이름을 비롯한 모든 식별자는 실행 컨텍스트에 등록된다. 실행 컨텍스트는 자바스크립트 엔진이 소스코드를 평가하고 실행하기 위해 필요한 환경을 제공하고 코드의 실행 결과를 실제로 관리하는 영역이다. 65 | 66 | ### 4.4 변수 선언의 실행 시점과 변수 호이스팅 67 | 68 | 다음 예제를 살펴보자 69 | 70 | ```js 71 | console.log(score); // undefined 72 | 73 | var score; // 변수 선언문 74 | ``` 75 | 76 | 변수 선언문보다 변수를 참조하는 코드가 앞에 있다. 77 | 78 | 따라서 `ReferenceError`가 발생할 것처럼 보인다. 하지만 `undefined`가 출력된다. 79 | 80 | > 그 이유는 변수 선언이 소스코드가 한 줄씩 순차적으로 실행되는 시점, 즉 런타임이 아니라 그 이전 단계에서 먼저 실행되기 때문이다. 81 | > 82 | > 이처럼 변수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징을 변수 호이스팅이라 한다. 83 | 84 | 사실 변수 선언뿐 아니라 `var`, `let`, `const`, `function`, `function*`, `class` 키워드를 사용해서 선언하는 모든 식별자는 호이스팅된다. 85 | 86 | 모든 선언문은 런타임 이전 단게에서 먼저 실행되기 때문이다. 87 | 88 | ### 4.5 값의 할당 89 | 90 | 변수 선언은 소스코드가 순차적으로 실행되는 시점인 런타임 이전에 먼저 실행되지만 값의 할당은 소스코드가 순차적으로 실행되는 시점인 런타임에 실행된다. 91 | 92 | ```js 93 | console.log(score); // undefined 94 | 95 | var score; 96 | score = 80; 97 | 98 | console.log(score); // 80 99 | ``` 100 | 101 | 변수 선언과 값의 할당을 하나의 문으로 단축 표현할 수도 있으므로 앞 예제는 다음 예제와 동일하게 동작한다. 102 | 103 | ```js 104 | console.log(score); // undefined 105 | 106 | var score = 80; 107 | 108 | console.log(score); // 80 109 | ``` 110 | 111 | ### 4.6 값의 재할당 112 | 113 | `var` 키워드로 선언한 변수는 값을 재할당할 수 있다. 114 | 115 | 재할당은 현재 변수에 저장된 값을 버리고 새로운 값을 저장하는 것이다. 116 | 117 | `var` 키워드로 선언한 변수는 선언과 동시에 `undefined`로 초기화되기 때문에 엄밀히 말하자면 변수에 처음으로 값을 할당하는 것도 사실은 재할당이다. 118 | 119 | 만약 값을 재할당할 수 없어서 변수에 저장된 값을 변경할 수 없다면 변수가 아니라 상수라 한다. 120 | 121 | > **const 키워드** 122 | > 123 | > ES6에서 도입된 const 키워드를 사용해 선언한 변수는 재할당이 금지된다. 즉, const 키워드는 단 한번만 할당할 수 있는 변수를 선언한다. 따라서 const 키워드를 사용하면 상수를 표현할 수 있다. 124 | 125 | ### 4.7 식별자 네이밍 규칙 126 | 127 | 식별자는 다음과 같은 네이밍 규칙을 준수해야 한다. 128 | 129 | - 식별자는 특수문자를 제외한 문자, 숫자, 언더스코어, 달러 기호를 포함할 수 있다. 130 | - 단, 식별자는 특수문자를 제외한 문자, 언더스코어, 달러 기호로 시작해야 한다. 숫자로 시작할 수 없다. 131 | - 예약어는 식별자로 사용할 수 없다. 132 | 133 | > **예약어** 134 | > 135 | > `await`, `break`, `case`, `catch`, `class`, `const`, `continue`, `debugger`, `default`, `delete`, `do`, `else,enum`, `export`, `extends`, `false`, `finally`, `for`, `function`, `if`, `implements`, `import`, `in`, `instanceof`, `interface`, `let`, `new`, `null`, `package`, `private`, `protected`, `public`, `return`, `super`, `static`, `switch`, `this`, `throw`, `true`, `try`, `typeof`, `var`, `void`, `while`, `with`, `yield` 136 | 137 | 일관성을 유지한다면 어떤 네이밍 컨벤션을 사용해도 좋지만 자바스크립트에서는 일반적으로 변수나 함수의 이름에는 카멜 케이스를 사용하고, 생성자 함수, 클래스의 이름에는 파스칼 케이스를 사용한다. 138 | 139 | `ECMAScript` 사양에 정의되어 있는 객체와 함수들도 카멜 케이스와 파스칼 케이스를 사용하고 있다. 140 | 141 | ## 05장 표현식과 문 142 | 143 | ### 5.1 값 144 | 145 | 값은 식(표현식)이 평가되어 생성된 결과를 말한다. 146 | 147 | 값은 다양한 방법으로 생성할 수 있다. 가장 기본적인 방법은 리터럴을 사용하는 것이다. 148 | 149 | ### 5.2 리터럴 150 | 151 | 리터럴은 사람이 이해할 수 있는 문자 또는 약속된 기호를 사용해 값을 생성하는 표기법을 말한다 152 | 153 | 리터럴을 사용하면 다음과 같이 다양한 종류의 값을 생성할 수 있다. 154 | 155 | | 리터럴 | 예시 | 비고 | 156 | |-|-|-| 157 | | 정수 리터럴 |`100`|| 158 | | 부동 소수점 리터럴 |`10.5`|| 159 | | 2진수 리터럴|`0b01000001`|0b로 시작| 160 | |8진수 리터럴|`0o101`|ES6에서 도입. 0o로 시작| 161 | |16진수 리터럴|`0x41`|ES6에서 도입. 0x로 시작| 162 | |문자열 리터럴|`'Hello'`, `"World"`|| 163 | |불리언 리터럴|`true`, `false`|| 164 | |null 리터럴|`null`|| 165 | |undefined 리터럴|`undefined`|| 166 | |객체 리터럴|`{ name: 'Lee', address: 'Sejong' }`|| 167 | |배열 리터럴|`[ 1, 2, 3 ]`|| 168 | |함수 리터럴|`function() {}`|| 169 | |정규 표현식 리터럴|`/[A-Z]+/g`|| 170 | 171 | ### 5.3 표현식 172 | 173 | 표현식은 값으로 평가될 수 있는 문이다. 즉, 표현식이 평가되면 새로운 값을 생성하거나 기존 값을 참조한다. 174 | 175 | 앞서 살펴본 리터럴은 값으로 평가된다. 따라서 리터럴도 표현식이다. 176 | 177 | 이 외에도 값을 참조하거나 산술 연산을 하거나 함수 호출을 하는 등 값으로 평가될 수 있는 문은 모두 표현식이다. 178 | 179 | ### 5.4 문 180 | 181 | > 문은 프로그램을 구성하는 기본 단위이자 최소 실행 단위다. 182 | 183 | 문은 여러 토큰으로 구성된다. 184 | 185 | > 토큰이란 여러 문법적인 의미를 가지며, 문법적으로 더 이상 나눌 수 없는 코드의 기본 요소를 의미한다. 186 | 187 | 문은 선언문, 할당문, 조건문, 반복문 등으로 구분할 수 있다. 188 | 189 | ```js 190 | // 변수 선언문 191 | var x; 192 | 193 | // 할당문 194 | x = 5; 195 | 196 | // 함수 선언문 197 | function foo () {} 198 | 199 | // 조건문 200 | if (x > 1) { console.log(x); } 201 | 202 | // 반복문 203 | for (var i = 0; i < 2; i++) { console.log(x); } 204 | ``` 205 | 206 | ### 5.5 세미콜론과 세미콜론 자동 삽입 기능 207 | 208 | 문의 끝에 붙이는 세미콜론은 옵션이다. 209 | 210 | 이는 자바스크립트 엔진이 소스코드를 해석할 때 문의 끝이라고 예측되는 지점에 세미콜론을 자동으로 붙여주는 **세미콜론 자동 삽입 기능(ASI)** 이 암묵적으로 수행되기 때문이다. 211 | 212 | ### 5.6 표현식인 문과 표현식이 아닌 문 213 | 214 | 표현식인 문과 표현식이 아닌 문을 구별하는 가장 간단하고 명료한 방법은 변수에 할당해 보는 것이다. 215 | 216 | ```js 217 | var foo = var x; // SyntaxError: Unexpected token var 218 | ``` 219 | -------------------------------------------------------------------------------- /01) 4. 변수 & 5. 표현식과 문/README.md: -------------------------------------------------------------------------------- 1 | # 4. 변수 & 5. 표현식과 문 2 | 3 | ## 정리 4 | 5 | - [춘식 - 메인 발표자](choonsik.md) 6 | - [뽀송](Pposong.md) 7 | - [세인트](saint.md) 8 | - 이안 9 | - [준](June.md) 10 | - [다나](dana.md) 11 | -------------------------------------------------------------------------------- /01) 4. 변수 & 5. 표현식과 문/dana.md: -------------------------------------------------------------------------------- 1 | # 4.변수 2 | ## 4.1 변수란 무엇인가? 왜 필요한가? 3 | 자바스크립트 엔진이 자바스크립트 코드를 계산하기 위해 기호(리터럴 + 연산자)의 의미를 알고 있어야하며 표현식도 해석(파싱)할 수 있어야함. 4 | 5 | 자바스크립트는 개발자의 직접적인 메모리 제어를 허용하지 않음. 6 | 만약 허용시, 값이 저장될 메모리 주소는 코드가 실행될 때 메모리의 상황에 따라 임의로 결정됨. **동일한 컴퓨터에서 동일한 코드를 실행해도 코드가 실행될 때마다 값이 저장될 메모리 주소가 변경** 메모리 주소를 통한 직접 접근은 옳지 않음. 7 | 8 | 기억하고 싶은 값을 메모리에 저장하고, 저장된 값을 읽어들여 재사용하기 위해 변수라는 메커니즘을 제공 9 | 10 | **변수** : 하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위해 붙인 이름 (값의 위치를 가리킴) 11 | 12 | 프로그래밍 언어의 컴파일러 또는 인터프리터에 의해 값이 저장된 메모리 공간의 주소로 치환되어 실행 13 | 14 | **변수명(식별자)** : 메모리 공간에 저장된 값을 식별할 수 있는 고유한 이름 15 | **변수 값** : 변수에 저장된 값 16 | **할당** : 변수에 값을 저장 17 | **참조** : 변수에 저장된 값을 읽어 들이는 것 18 | 19 | ## 4.2 식별자 20 | 어떤 값을 구별해서 식별할 수 있는 고유한 이름 21 | 어떤 값이 저장되어 있는 **메모리 주소**를 기억해야함. 22 | 메모리 상에 존재하는 어떤 값을 식별할 수 있는 이름 23 | -> `변수`, `함수`, `클래스` 등의 이름은 모두 식별자 24 | 선언에 의해 자바스크립트 엔진에 식별자의 존재를 알림 25 | 26 | ## 4.3 변수 선언 27 | 값을 저장하기 위한 메모리 공간을 확보하고 변수 이름과 확보된 메모리 공간의 주소를 연결해 값을 저장할 수 있도록 준비하는 것 28 | 29 | 변수 선언에 의해 확보된 메모리 공간은 확보가 해제되기 전까지 보호 30 | 변수를 사용하기 위해선 반드시 선언이 필요 31 | -> `var`, `let`, `const` 키워드 사용 32 | 33 | > #### var vs let, const 34 | > var는 블록레벨 스코프 지원 ❌ 함수레벨 스코프 지원 ⭕️ 35 | > 뜻하지 않게 변수가 전역으로 선언되는 문제점 발생 36 | 37 | ### var키워드를 이용해 변수 선언하기 38 | ```javascript 39 | var score; 40 | ``` 41 | 1. **선언 단계** : 변수 이름을 등록하고 메모리에 저장할 공간 확보 42 | 2. **초기화 단계** : 확보된 메모리 공간에는 undefined 값이 암묵적으로 할당되어 초기화 43 | 44 | var 선언은 선언 단계와 초기화 단계가 동시에 진행 45 | 만약 초기화 단계를 거치지 않으면 확보된 메모리 공간에는 이전에 다른 어플리케이션에서 사용됐던 값(쓰레기값)이 남아있을 수 있다. 46 | -> var는 암묵적으로 초기화를 수행하므로 안전함. 47 | 48 | 만약 선언하지 않은 식별자에 접근시 `ReferenceError`가 발생함 49 | 50 | 51 | > #### 키워드 (keyword) 52 | > 자바스크립트 코드를 해석하고 실행하는 자바스크립트 엔진이 수행할 동작을 규정한 일종의 명령어 53 | 54 | ## 4.4 변수 선언의 실행 시점과 변수 호이스팅 55 | 자바스크립트 코드는 인터프리터에 의해 한 줄씩 순차적으로 실행됨. 변수 선언이 소스코드가 한 줄씩 순차적으로 실행되는 시점(런타임)에 실행되는 것이 아니라 그 전 단계에서 먼저 실행 56 | == **변수 호이스팅** 57 | 58 | ## 4.5 값의 할당 59 | ```javascript 60 | var score; // 변수 선언 61 | score = 80; // 변수 할당 62 | 63 | var score = 80; 64 | ``` 65 | 66 | 하나의 문장으로 단축해도 변수 선언과 변수 할당은 각각 실행됨. 변수 선언은 런타임 이전에 먼저 실행되지만, 값의 할당은 런타임에 실행됨. 67 | 68 | 변수에 값을 할당할 때는 이전 값 undefined가 저장되어 있던 메모리 공간을 지우고 그 메모리 공간에 할당 값을 저장하는 것이 아니라 **새로운 메모리 공간을 확보하고 그곳에 할당 값을 저장** 69 | 70 | ## 4.6 값의 재할당 71 | var로 선언한 변수는 현재 변수에 저장된 값을 버리고 새로운 값을 저장(재할당)할 수 있다. 만약 값을 재할당할 수 없어 변수에 저장된 값을 변경할 수 없다면 상수(constant) -> const 이용 72 | 73 | 앞서 언급한 대로 이전 값이 있던 곳에 값을 바꾸는 것이 아니라 새로운 메모리 공간을 확보하고 새 값을 저장한다. 이 때 이전 값이 저장되어 있던 저장 공간이 어떤 변수와도 연결되어 있지 않다면, 가비지 콜렉터에 의해 메모리에서 자동 해제됨. 74 | 75 | > #### 가비지 콜렉터 76 | > 애플리케이션이 할당한 메모리 공간을 주기적으로 검사하여 어떤 식별자도 참조하지 않는 메모리 공간을 해체하는 기능 77 | > 자바스크립트는 가비지콜렉터를 내장하고 있는 매니지드 언어로 가비지콜렉터를 통해 메모리 누수 방지 78 | 79 | 80 | 81 | > #### unmanaged language vs managed language 82 | > unmanaged language 83 | > - 개발자가 명시적으로 메모리를 할당하고 해제하기 위해 malloc()과 free() 같은 저수준 메모리 제어 기능을 제공 84 | > - 개발자의 역량에 따라 최적의 성능을 확보할 수 있지만 치명적 오류 생산 가능성도 존재 85 | > 86 | > managed language 87 | > - 메모리 할당 및 해제를 위한 메모리 관리 기능을 언어 차원에서 담당 88 | > - 개발자가 명시적으로 메모리 할당 및 해제 불가능 89 | > - 일정한 생산성 확보할 수 있다는 장점 90 | > - 성능면에서 손실 발생 91 | 92 | ## 4.7 식별자 네이밍 규칙 93 | 1. 식별자는 특수문자를 제외한 문자, 숫자, 언더스코어(_), 달러 기호($) 포함 가능 94 | 2. 단, 숫자로 시작은 허용되지 않음. 95 | 3. 예약어는 식별자로 사용할 수 없음. 96 | 4. 쉼표를 이용해 하나의 문에서 여러 변수를 한번에 선언할 수 있다. 97 | 5. ES5부터 유니코드를 허용하나 권장되지 않는다. 98 | 6. 대소문자를 구별 99 | 100 | ### 네이밍 컨벤션의 종류 101 | |네이밍 컨벤션|예시| 102 | |--|----| 103 | |**카멜 케이스**| camelCase | 104 | |**스네이크 케이스**| snake_case | 105 | |**파스칼 케이스**| PascalCase | 106 | |**헝가리언 케이스**| typeHungarianCase| 107 | 108 | # 표현식과 문 109 | ## 5.1 값 110 | **값** : 식을 해석해서 값을 생성하거나 참조되어 생성된 결과 111 | 112 | ## 5.2 리터럴 113 | 사람이 이해할 수 있는 문자 또는 약속된 기호를 사용해 값을 생성하는 표기법 114 | - 숫자 리터럴 3을 코드에 기술하면 자바스크립트 엔진은 이를 평가해 숫자 값 3을 생성 115 | 116 | 자바스크립트 엔진은 코드가 실행되는 시점인 런타임에 리터럴값을 평가해 값을 생성 - 리터럴은 값을 생성하기 위해 미리 약속한 표기법 117 | 118 | ## 5.3 표현식 119 | 값으로 평가될 수 있는 문 120 | 표현식이 평가되면 새로운 값을 생성하거나 기존 값을 참조 121 | 값으로 평가될 수 있는문은 모두 표현식 122 | 표현식과 표현식이 평가된 값은 동등한 관계(동치) 123 | 124 | ## 5.4 문 125 | **문(statement)** : 프로그램을 구성하는 기본 단위이자 최소 실행 단위 126 | **토큰** : 문은 여러 토큰으로 구성, 문법적인 의미를 가지며 문법적으로 더 이상 나눌 수 없는 코드의 기본 요소를 의미 127 | 128 | ## 5.5 세미콜론과 세미콜론 자동 삽입 기능 129 | 0개 이상의 문을 중괄호로 묶은 코드블록({}) 뒤에는 세미콜론을 붙이지 않는다. 130 | -> 언제나 문의 종료를 의미하는 **자체 종결성**을 갖기 때문 131 | 자바스크립트 엔진은 세미콜론 자동 삽입 기능이 암묵적으로 수행 132 | 133 | ## 5.6 표현식인 문과 표현식이 아닌 문 134 | 표현식은 문의 일부일 수도 있고 그 자체로 문이 될 수 있음. 135 | - 표현식인 문은 값으로 평가될 수 있는 문 136 | - 표현식이 아닌 문은 값으로 평가될 수 없는 문 137 | 138 | 둘을 구분하는 가장 간단하고 명료한 방법은 변수에 할당해보는 것. 표현식인 문은 값으로 평가되므로 변수에 할당할 수 있다. 139 | 140 | 141 | -------------------------------------------------------------------------------- /01) 4. 변수 & 5. 표현식과 문/saint.md: -------------------------------------------------------------------------------- 1 | ## 04. 변수 2 | 3 | 변수 (variable) : 하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위해 붙인 이름 4 | 5 | Mdn에서의 정의 : 값을 저장하기 위해 명명된 위치 6 | 7 | 8 | 9 | 메모리 공간에 저장된 값을 다시 읽어 재사용할 수 있도록 값이 저장된 메모리 공간에 상징적인 이름을 붙인 것이 바로 변수 10 | 11 | 12 | 13 | 14 | 15 | ##### 변수가 왜 필요할까? 16 | 17 | 연산 결과와 같은 특정한 값을 재사용하려면 값이 저장되어 있는 메모리에 접근해야 되는데 메모리 주소를 통해 값에 직접 접근하는 것보다 변수를 통해 안전하게 값에 접근하기 위함 18 | 19 | 20 | 21 | 변수명 (변수이름) : 메모리 공간에 저장된 값을 식별할 수 있는 고유한 이름 22 | 23 | 변수값 : 변수에 저장된 값 24 | 25 | 할당 (assignment / 대입, 저장) : 변수에 값을 저장하는 것 26 | 27 | 참조 (reference) : 변수에 저장된 값을 읽어 들이는 것 28 | 29 | 30 | 31 | 식별자(identifier) : 어떤 값을 구별해서 식별할 수 있는 고유한 이름. 값이 아니라 메모리 주소를 기억하고 있음. 다시 말해서 메모리 주소에 붙인 이름이라고도 할 수 있음 32 | 33 | 변수명뿐 아니라 변수, 함수, 클래스 등의 이름을 모두 식별자라고 함 34 | 35 | 36 | 37 | #### 변수 선언 (variable declaration) 38 | 39 | 변수 선언 : 변수를 생성하는 것. 값을 저장하기 위한 메모리 공간을 확보하고 변수 이름과 확보된 메모리 공간의 주소를 연결하여 값을 저장할 수 있게 준비하는 것. 40 | 41 | 변수를 사용하기 위해서는 반드시 선언이 필요하며, 변수를 선언할 때는 var, let, const 키워드를 사용함 42 | 43 | ```js 44 | var score; 45 | ``` 46 | 47 | 위의 예시문에서는 변수를 선언하고 값을 할당하지 않았는데, 자바스크립트 엔진에 의해 확보된 메모리 공간에 undefined 라는 값을 할당하여 초기화 48 | 49 | 이를 initialization 이라고 하며 var 키워드에서만 해당. let, const 로 선언한 변수는 선언 전에 사용시 ReferenceError가 발생. 50 | 51 | 52 | 53 | ##### 자바스크립트 엔진이 변수 선언을 수행하는 과정 54 | 55 | 1. 선언 단계 : 변수 이름을 등록해서 자바스크립트 엔진에 변수의 존재를 알린다. 56 | 2. 초기화 단계 : 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefined 를 할당하여 초기화 57 | 58 | 59 | 60 | 변수를 사용하기 위해서는 반드시 변수 선언이 필요하며, 선언하지 않은 식별자에 접근하면 ReferenceError(참조 에러)가 발생. 61 | 62 | 63 | 64 | 65 | 66 | #### 변수 호이스팅 67 | 68 | 변수 선언은 런타임 시점에서 실행되는 것이 아니라 그 이전 단계에서 실행되게 됨. 69 | 70 | 따라서 변수 선언문은 코드의 선두로 끌어 올려진 것처럼 동작하는데 이를 변수 호이스팅이라 함. 71 | 72 | ```js 73 | console.log(scroe); // undefined 74 | 75 | var score; 76 | ``` 77 | 78 | 위의 예시문에서 score 변수의 선언이 런타임보다 먼저 실행되기 때문에 ReferenceError를 발생하는게 아닌 undifined 를 출력 79 | 80 | 81 | 82 | #### 할당 (assignment) 83 | 84 | 할당 연산자 = 를 사용하며, 우변의 값을 좌변의 변수에 할당 85 | 86 | ```js 87 | var score; // 변수 선언 88 | score = 80; // 값의 할당 89 | ``` 90 | 91 | 92 | 93 | 변수 선언과 할당을 하나의 문으로 표현할 수도 있다. 94 | 95 | ```js 96 | var score = 80; 97 | ``` 98 | 99 | 위처럼 선언과 할당을 하나의 문으로 단축 표현해도 자바스크립트 엔진은 2개의 문으로 나누어 각각 실행하며, 100 | 101 | 변수 선언은 런타임 이전에 값의 할당은 소스코드가 순차적으로 실행되는 시점인 런타임에 실행 102 | 103 | 104 | 105 | #### 값의 재할당 106 | 107 | 재할당 : 이미 값이 할당되어 있는 변수에 새로운 값을 또다시 할당하는 것 108 | 109 | ```js 110 | var score = 80; 111 | score = 90; 112 | ``` 113 | 114 | 재할당을 하게 되면 score 변수의 값은 이전 값 80에서 재할당한 값 90으로 변경되는데 이 때 80이 저장되어있던 메모리 값을 지우고 90을 할당하는 것이 아니라, 115 | 116 | 새로운 메모리 공간을 확보하고 그 메모리 공간에 숫자 값 90을 할당한다. 117 | 118 | 119 | 120 | 이 때 이전 값인 80과 undefined 는 어떤 식별자와도 연결되지 않은 상태가 되고 이러한 불필요한 값들은 가비지 콜렉터에 의해 메모리에서 자동 해제됨. 121 | 122 | 123 | 124 | ##### 식별자 네이밍 규칙 125 | 126 | - 특수문자를 제외한 문자, 숫자, 언더스코어(_), 달러기호($)를 포함할 수 있다. 127 | - 숫자로 시작하는 것은 금지 128 | - 예약어는 식별자로 사용 금지 129 | 130 | | abstract | arguments | await* | boolean | 131 | | :------: | :--------: | :----------: | :-------: | 132 | | break | byte | case | catch | 133 | | char | class* | const | continue | 134 | | debugger | default | delete | do | 135 | | double | else | enum* | eval | 136 | | export* | extends* | false | final | 137 | | finally | float | for | function | 138 | | goto | if | implements | import* | 139 | | in | instanceof | int | interface | 140 | | let* | long | native | new | 141 | | null | package | private | protected | 142 | | public | return | short | static | 143 | | super* | switch | synchronized | this | 144 | | throw | throws | transient | true | 145 | | try | typeof | var | void | 146 | | volatile | while | with | yield | 147 | 148 | Words marked with* are new in ECMAScript 5 and 6. 149 | 150 | 151 | 152 | ##### 네이밍 컨벤션 : 가독성 좋게 단어를 구분하기 위해 규정한 명명 규칙 153 | 154 | ```js 155 | // 카멜 케이스 (camelCase) : 중간 단어만 첫 글자를 대문자로 156 | var firstName; 157 | 158 | // 파스칼 케이스 (PascalCase) : 첫 단어와 중간 단어 모두 첫 글자를 대문자로 159 | var FirstName; 160 | 161 | // 스네이크 케이스 (snake_case) : 단어 사이를 언더바(_)로 연결 162 | var first_name; 163 | 164 | // 헝가리언 케이스(typeHungarianCase) : 변수의 타입을 같이 명시 165 | var strFirstName; // type + identifier 166 | var $elem = document.getElementById('myId'); // DOM node 167 | var 168 | ``` 169 | 170 | 171 | 172 | ## 05. 표현식과 문 173 | 174 | # 값 175 | 176 | > 값(value)는 식(expression)이 평가(evaluate)되어 생성한 결과를 말한다. 177 | 178 | 변수는 하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위해 붙인 이름이다. 179 | 180 | 따라서 `변수에 할당`되는 것은 값이다. 181 | 182 | # 리터럴 183 | 184 | > 리터럴(literal)은 사람이 이해할 수 있는 문자 또는 약속된 기호를 사용해 값을 생성하는 표기법(notation)을 말한다. 185 | 186 | 리터럴은 값을 생성하기 위해 미리 약속한 표기법이라고 할 수 있다. 187 | 188 | | 리터럴 | 예시 | 189 | | ------------------ | --------------------------------- | 190 | | 정수 리터럴 | 100 | 191 | | 문자열 리터럴 | 'Hello', "world | 192 | | 불리언 리터럴 | true, false | 193 | | null 리터럴 | null | 194 | | undefined 리터럴 | undefined | 195 | | 객체 리터럴 | {name : "Lee", address : 'Seoul'} | 196 | | 배열 리터럴 | [1, 2, 3] | 197 | | 함수 리터럴 | function() {} | 198 | | 정규 표현식 리터럴 | /[A-Z]+/g | 199 | 200 | 201 | 202 | # 표현식 203 | 204 | > 표현식(expression)은 값으로 평가될 수 있는 문(statement)이다. 즉, 표현식이 평가되면 새로운 값을 생성하거나 기존 값ㅇ르 참조한다. 205 | 206 | 값으로 평가될 수 있는 문은 모두 표현식이다. 207 | 208 | # 문 209 | 210 | > 문(statement)은 프로그램을 구성하는 기본 단위이자 최소 실행 단위다. 211 | 212 | ![img](https://borachoi.notion.site/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Ff298e2f2-b9c6-470f-a1bd-6f58736a5c99%2FUntitled.png?table=block&id=d1469c8f-7445-492b-aff6-797ea10261bd&spaceId=2734092e-8132-4e66-9239-0ceddcedf0eb&width=2000&userId=&cache=v2) 213 | 214 | 토큰(token)이란 문법적인 의미를 가지며, 문법적으로 더 이상 나눌 수 없는 코드의 기본 요소를 의미한다. 215 | 216 | 문은 선언문, 할당문, 조건문, 반복문 등으로 구분할 수 있다. 217 | 218 | ```jsx 219 | //변수 선언문 220 | var x; 221 | 222 | //할당문 223 | x = 5; 224 | 225 | //함수 선언문 226 | function foo(){} 227 | 228 | //조건문 229 | if(x>1){console.log(x);} 230 | 231 | //반복문 232 | for(var i =0;i<2;i++) {console.log(i); } 233 | ``` 234 | 235 | # 세미콜론과 세미콜론 자동 삽입 기능 236 | 237 | 세미콜론(;)은 문의 종료를 나타낸다. 자바스크립트 엔진은 세미콜론으로 문이 종료한 위치를 파악하고 순차적으로 하나씩 문을 실행한다. 문을 끝낼 때는 세미콜론을 붙여야 한다. 단, 0개 이상의 문을 중괄호로 묶은 코드 블록 뒤에는 세미콜론을 붙이지 않는다. 이러한 코드 블록은 언제나 문의 종료를 의미하는 자체 종결성(self closing)을 갖기 때문이다. 238 | 239 | 세미콜론은 생략 가능하다. 자사브크립트 엔진이 세미콜론 자동 삽입 기능(ASI, automatic semicolon insertion)이 암묵적으로 수행되기 때문이다. 240 | 241 | # 표현식인 문과 표현식이 아닌 문 242 | 243 | 표현식은 문의 일부일 수도 있고 그 자체로 문이 될 수도 있다. 244 | 245 | ```jsx 246 | //변수 선언문은 값으로 평가될 수 없으므로 표현식이 아니다. 247 | var x; 248 | //1,2,1+2,x=1+2는 모두 표현식이다. 249 | //x=1 + 2는 표현식이면서 완전한 문이기도 하다. 250 | x=1 + 2; 251 | ``` 252 | 253 | 표현식인 문은 값으로 평가될 수 있는 문이며, 표현식이 아닌 문은 값으로 평가될 수 없는 문을 말한다. 254 | 255 | 표현식인 문과 표현식이 아닌 문을 구별하는 가장 간단하고 명료한 방법은 변수에 할당해 보는 것이다. 256 | 257 | 표현식인 문은 값으로 평가되므로 변수에 할당할 수 있다. 하지만 표현식이 아닌 문은 값으로 평가할 수 없으므로 변수에 할당하면 에러가 발생한다 258 | 259 | ```jsx 260 | //변수 선언문은 표현식이 아닌 문이다. 261 | var x; 262 | 263 | //할당문은 그 자체가 표현식이지만 완전한 문이기도 하다. 즉, 할당문은 표현식인 무니다. 264 | x = 100; 265 | 266 | //표현식이 아닌문은 값처럼 사용할 수 없다. 267 | var foo = var x; //SyntaxError : Unexpected token var 268 | ``` -------------------------------------------------------------------------------- /02) 6. 데이터 타입 & 7. 연산자/June.md: -------------------------------------------------------------------------------- 1 | # 6. 데이터 타입 2 | 3 | - 데이터 타입 = 값의 종류 4 | - 자바스크립트에서는 7개의 데이터 타입을 제공하는데 원시 타입과 객체 타입으로 분류 가능 5 | - 원시 타입: number, string, boolean, undefined, null, symbol 6 | - 객체 타입: object, function, array, etc... 7 | 8 | ## 6.1 숫자 타입 9 | 10 | - 자바스크립트는 하나의 숫자 타입만 존재한다. 11 | - 모든 수를 실수로 처리하며, 정수만 표현하기 위한 데이터 타입이 별도로 존재하지 않는다. (C와 Java와는 다름) 12 | 13 | ```javascript 14 | Infinity // 양의 무한대 15 | -Infinity // 음의 무한대 16 | NaN // 산술 연산 불가 17 | ``` 18 | 19 | - 자바스크립트는 세 가지 특별한 값도 위와 같이 표현할 수 있다. 20 | - 자바스크립트는 **대소문자를 구별**하므로 `NaN`을 `NAN`, `Nan`, `nan`과 같이 표현하면 에러가 난다. 21 | 22 | ## 6.2 문자열 타입 23 | 24 | - 문자열 타입은 텍스트 데이터를 나타내는 데 사용한다. 25 | - 작은 따옴표(''), 큰따옴표(""), 백틱(``)으로 표현가능하다. (백틱은 es6 문법) 26 | - 위의 것들로 감싸지 않으면 **식별자**로 인식한다. 27 | 28 | ## 6.3 템플릿 리터럴 29 | 30 | - ES6부터 새로나온 표기법으로, 백틱(``)을 사용해서 표현한다. 31 | 32 | ```javascript 33 | // 멀티라인 제공 34 | const backtic = ` 35 |
36 |
37 | `; 38 | 39 | // 표현식 삽입 가능 40 | let name = "hyeonsu"; 41 | 42 | const backtic2 = `제 이름은 ${name}입니다.`; 43 | ``` 44 | 45 | ## 6.4 불리언 타입 46 | 47 | - 불리언 타입은 논리적 참, 거짓을 나타내는 `true`와 `false`밖에 없다. 48 | 49 | ## 6.5 undefined 타입 50 | 51 | - `undefined` 타입의 값은 `undefined`가 유일하다. 52 | - `var` 키워드로 선언한 변수는 선언과 동시에 변수에 `undefined`가 할당된다. 53 | - 이처럼 `undefined`는 자바스크립트 엔진이 변수를 초기화할 때 사용하는 값이므로 변수에 값이 없다고 표현하고 싶을 때는 `undefined` 대신에 `null`을 써서 혼란을 줄이자. 54 | 55 | ## 6.6 null 타입 56 | 57 | - `null` 타입 또한 `null`이 유일하다. 58 | - 자바스크립트는 대소문자를 구분하므로 스펠링에 주의해야한다. 59 | - `undefined`와는 다르게 명시적으로 `없다`라고 표현하고 싶을 때 `null`을 사용한다. 60 | 61 | ## 6.7 심벌 타입 62 | 63 | - ES6에서 추가된 7번째 타입 64 | - 변경 불가능한 원시 타입의 값 65 | - 다른 값과 중복 되지 않는 유일무이한 값 66 | 67 | ## 6.8 객체 타입 68 | 69 | - 자바스크립트를 이루고 있는 거의 모든 것이 객체이다. 70 | 71 | ## 6.9 데이터 타입의 필요성 72 | 73 | - 데이터 타입이 필요한 이유는 아래와 같다. 74 | - 값을 저장할 때 확보해야 하는 메모리 공간의 크기를 결정하기 위해 75 | - 값을 참조할 때 한 번에 읽어 들여야 할 메모리 공간의 크기를 결정하기 위해 76 | - 메모리에서 읽어 들인 2진수를 어떻게 해석할지 결정하기 위해 77 | 78 | ## 6.10 동적 타이핑 79 | 80 | - 자바스크립트는 동적 타입 언어로, 변수를 선언할 때 타입을 선언하지 않는다. 81 | - `var`, `let`, `const`와 같은 키워드로 변수를 선언할 뿐이다. 82 | - 자바스크립트의 변수는 선언이 아닌 할당에 의해 타입이 결정된다. (타입추론) 83 | - 그리고 재할당에 의해 변수의 타입은 언제든지 동적으로 변할 수 있다. 84 | 85 | ### 6.10.2 동적 타입 언어와 변수 86 | 87 | - 자바스크립트가 동적 언어라서 불편한점은 다음과 같다. 88 | - 변화하는 변수 값을 추적하기 어려울 수 있다. 89 | - 변수의 타입이 고정되어 있지 않고, 동적으로 변하는 동적 타입 언어의 변수는 값의 변경에 의해 타입도 언제든지 변경될 수 있다. 90 | - 자바스크립트 엔진에 의해서 타입이 자동으로 변환되기도 한다. = 신뢰성이 떨어진다. 91 | 92 | - 그럼 위의 불편한점을 방지하기 위한 주의사항들은 다음과 같다. 93 | - 변수는 꼭 필요한 곳에 한해서 제한적으로 사용 94 | - 변수의 스코프를 좁게 만들어 부작용 억제 95 | - 전역 변수는 최대한 피하기 96 | - 변수보다는 상수 사용 97 | - 변수 이름 잘 짓기 98 | 99 | # 7. 연산자 100 | 101 | - 연산자는 하나 이상의 표현식을 대상으로 산술, 할당, 비교, 논리, 타입, 지수 연산등을 수행해서 **하나의 값**을 만든다. 102 | 103 | ## 7.1 산술 연산자 104 | 105 | - 수학적 계산을 수행해 새로운 숫자 값을 생성 106 | - 산술 연산이 불가능하면 `NaN` 반환 107 | 108 | ### 7.1.1 이항 산술 연산자 109 | 110 | - 덧셈(+), 뺼셈(-), 곱셈 (*), 나눗셈(/), 나머지(%) 111 | 112 | ### 7.1.2 단항 산술 연산자 113 | 114 | - `++` (증가) 115 | - `--` (감소) 116 | - `+` (어떠한 효과도 없다.) 117 | - `-` (양수를 음수로, 음수를 양수로 반전한 값을 리턴) 118 | 119 | ### 7.1.3 문자열 연결 연산자 120 | 121 | - `+` 연산자는 피연산자 중에 하나 이상이 문자열이면 문자열 연결 연산자로 동작한다. 122 | 123 | ```javascript 124 | '1' + 2 // '12', 암묵적 타입 변환, 타입 강제 변환이 작동 125 | 1 + '2' // '12' 126 | 127 | 1 + true // 2, true = 1로 변환 128 | 1 + false // 1, false = 0으로 변환 129 | 130 | 1 + null // 1, null = 0으로 변환 131 | 132 | 1 + undefined // NaN, undefined는 변환되지 않는다. 133 | ``` 134 | 135 | ## 7.2 할당 연산자 136 | 137 | - 우항에 있는 피연산자들의 평가 결과를 좌항에 있는 변수에 할당 138 | 139 | ## 7.3 비교 연산자 140 | 141 | - 좌항과 우항의 피연산자를 비교한 다음 그 결과를 불리언 값으로 반환 142 | 143 | ### 7.3.1 동등/일치 비교 연산자 144 | 145 | - `==`: 동등 비교 (값만 확인) 146 | - `===`: 일치 비교 (타입까지 확인) 147 | - `!=`: 부동등 비교 (값만 확인) 148 | - `!==`: 불일치 비교 (타입까지 확인) 149 | 150 |
151 | 152 | - `===`에서 `NaN`은 자기 자신과 일치하지 않는 유일한 값이다. 153 | 154 | ## 7.4 삼항 조건 연산자 155 | 156 | ```javascript 157 | var result = '조건' ? 'pass' : 'fail'; 158 | ``` 159 | 160 | - 조건에 따라 값으로 평가하려면 삼항 조건 연산자를 사용 161 | - 하지만 조건에 따라 수행해야 할 문이 여러 개라면 `if - else`문이 가독성이 더 좋음 162 | 163 | ## 7,5 논리 연산자 164 | 165 | - `||`: 논리합 연산자 166 | - `&&`: 논리곱 연산자 167 | - `!`: 논리부정 연산자 168 | 169 | ## 7.6 쉼표 연산자 170 | 171 | ```javascript 172 | var x, y, z; 173 | 174 | x = 1, y = 2, z = 3; // 3 175 | ``` 176 | 177 | ## 7.7 그룹 연산자 178 | 179 | - `()` 소괄호로 피연산자를 감싸서 표현식에서 가장 먼저 평가되도록 할 수 있다. 180 | 181 | ## 7.8 typeof 연산자 182 | 183 | - 피연산자의 데이터 타입을 문자열로 반환 184 | - string, number, boolean, undefined, symbol, object, function 중에 하나 반환 185 | 186 | ## 7.9 지수 연산자 187 | 188 | - ES7에서 도입된 연산자 189 | 190 | ```javascript 191 | 2 ** 2 // 4 192 | 2 ** 0 // 1 193 | 2 ** -2 // 0.25 194 | ``` 195 | 196 | - 이전에는 `Math.pow` 메서드를 사용했다. 197 | 198 | ## 7.10 그 외의 연산자 199 | 200 | - `?.`: 옵셔널 체이닝 연산자 201 | - `??`: null 병합 연산자 202 | - `delete`: 프로퍼티 삭제 203 | - `new`: 생성자 함수를 호출할 때 사용하여 인스턴스 생성 204 | - `instanceof`: 좌변의 객체가 우변의 생성자 함수와 연결된 인스턴스인지 판별 205 | - `in`: 프로퍼티 존재 확인 206 | -------------------------------------------------------------------------------- /02) 6. 데이터 타입 & 7. 연산자/README.md: -------------------------------------------------------------------------------- 1 | # 6. 데이터 타입 & 7. 연산자 2 | 3 | ## 정리 4 | 5 | - [춘식](choonsik.md) 6 | - [뽀송 - 메인발표자](Pposong.md) 7 | - [세인트](saint.md) 8 | - 이안 9 | - [준](June.md) 10 | - [다나](dana.md) 11 | -------------------------------------------------------------------------------- /02) 6. 데이터 타입 & 7. 연산자/dana.md: -------------------------------------------------------------------------------- 1 | # 6. 데이터 타입 2 | 원시 타입 : number, string, boolean, undefined, null, Symbol, Bigint 3 | 객체 타입 : 객체, 함수, 배열 등 4 | 5 | > #### [BigInt](https://ko.javascript.info/bigint) 6 | > 숫자 끝에 n을 붙이거나 BigInt 함수에 문자열이나 숫자를 넣어 BigInt 타입을 지정 7 | 8 | 각각의 타입들은 확보해야할 메모리 공간의 크기도 다르고, 해석되는 방식도 다름 9 | 10 | ## 숫자 타입 11 | 숫자 타입의 값은 배정밀도 64비트 부동소수점 형식을 따름. 12 | > #### [배정밀도 64비트 부동소수점 형식](https://vanillaani.tistory.com/6) 13 | > 십진수인 소수를 이진수로 변환하고 소수점을 1.xxx 형식이 될 때까지 오른쪽 또는 왼쪽으로 옮긴 뒤, 소수점 오른쪽에 해당하는 수를 가수부분에 넣는데 이 수가 표현 자리수보다 넘어서게 되면 나머지 부분에서 반올림 처리를 하면서 근사값이 저장됨. -> 수의 계산이 정확하게 나오지 않는 이유 14 | >
15 | > 소수점 계산을 올바르게 하는 법 16 | > 1. toFixed 사용
17 | > 2. Math.round(x) 사용 18 | >
19 | 20 | 모든 수를 실수로 처리하며 정수만 표현하기 위한 데이터 타입이 별도로 존재하지 않음. 21 | 22 | 숫자타입은 추가적으로 다음의 값도 포함함 23 | - `infinity` : 양의 무한대 24 | - `-infinity` : 음의 무한대 25 | - `NaN` : 산술 연산 불가 (대소문자 주의) 26 | 27 | ## 문자열 타입 28 | 텍스트 데이터를 나타내는 데 사용 29 | 문자열은 0개 이상의 16비트 유니코드 문자의 집합으로 대부분의 문자 표현 가능 30 | 31 | 자바스크립트의 문자열은 다른 언어와 달리 원시타입이며 변경 불가능한 값 32 | 33 | ## 템플릿 리터럴 34 | 편리한 문자열 처리기능을 제공 35 | 런타임에 일반 문자열로 변환되어 처리 36 | 백틱(\`)을 사용해 표현 37 | 38 | ### 멀티라인 문자열 39 | 일반 문자열 내에서는 개행이 허용되지 않음 40 | 공백을 표현하기 위해 백슬래시로 시작하는 이스케이프 시퀀스를 사용해야함. 41 | 42 | > #### 라인 피드와 캐리지 리턴 43 | > **라인 피드(LF, Line Feed)** : 커서를 정지한 상태에서 종이를 한 줄 올리는 것 44 | > **캐리지 리턴(CR, Carriage Return)** : 종이를 움직이지 않고 커서를 맨 앞 줄로 이동 45 | > 46 | > 초창기 컴퓨터는 CRLF(\r\n)를 모두 사용 47 | > 현대 운영체제는 운영체제 별로 다른 개행 문자를 사용하기 때문에 서로 개행문자를 인식하지 못함. 일반적으로 LF를 사용해 개행 48 | 49 | 일반 문자열과 달리 템플릿 리터럴 내에서는 이스케이프 시퀀스를 사용하지 않고도 줄바꿈이 허용되며 공백도 그대로 적용 50 | 51 | ### 표현식 삽입 52 | `${}`을 이용해 표현식을 감싸 문자열 사이에 삽입 - 문자열로 타입이 강제로 변환됨 53 | 54 | ## undefined 타입 55 | 개발자가 의도적으로 할당하기 위한 갑싱 아니라 자바스트립트 엔진이 변수를 초기화 할 때 사용하는 값 56 | -> 변수에 값이 없다는 것을 의도적으로 표현하고 싶을 때는`null` 사용 57 | 58 | ## null 타입 59 | 변수에 null을 할당하는 것은 변수가 이전에 참조하던 값을 더 이상 참조하지 않겠다는 의미 60 | 이전에 할당되어 있던 값에 대한 참조를 명시적으로 제거 -> 가비지 콜렉션 수행 61 | 62 | 함수가 유효한 값을 반환할 수 없는 경우 명시적으로 null 반환 63 | 64 | ## 심벌 타입 65 | 변경 불가능한 원시 타입의 값 66 | 다른 값과 중복되지 않는 유일무이한 값으로 유일한 프로퍼티 키를 만들기 위해 사용 67 | 68 | 보통 원시값은 리터럴을 통해 생성하지만 심벌은 Symbol 함수를 통해 생성됨 69 | 70 | ## 데이터 타입의 필요성 71 | - 값을 저장할 때 확보해야 하는 메모리 공간의 크기를 결정하기 위해 72 | - 값을 참조할 때 한 번에 읽어 들여야 할 메모리 공간의 크기를 결정하기 위해 73 | - 메모리에서 읽어 들인 2진수를 어떻게 해석할 지 결정하기 위해 74 | 75 | ## 동적 타이핑 76 | ### 동적 타입 언어와 정적 타입 언어 77 | **정적 타입 언어** 78 | - 변수를 선언할 때 변수에 할당할 수 있는 데이터 타입을 사전에 선언해야 함(명시적 타입 선언) 79 | - 컴파일 시점에서 타입 체크 -> 런타임 에러를 줄임 80 | - C, C++, Java 등등 81 | 82 | **동적 타입 언어** 83 | - 어떠한 데이터 타입의 값이라도 자유롭게 할당, 변경 가능 84 | - 값을 할당하는 시점에서 변수의 타입이 동적으로 결정 (동적 타이핑) 85 | - 선언이 아닌 할당에 의해 타입 결정 (타입 추론) 86 | - Javascript, Python 등등 87 | 88 | ### 동적 타입 언어와 변수 89 | 복잡한 프로그램에서 변화하는 변수의 값을 추적하기 어려움 90 | 개발자의 의도와 상관 없이 타입이 자동으로 변환되기도 함 91 | -> 유연성은 높지만 신뢰성은 떨어짐 92 | 93 | **주의사항** 94 | 1. 변수는 꼭 필요한 경우에 한해 제한적으로 사용 95 | 2. 변수의 스코프를 최대한 좁게 만듦 96 | 3. 전역 변수의 사용 최소화 97 | 4. 변수보다 상수 사용 98 | 5. 변수 이름은 변수의 목적이나 의미 파악이 쉽게 네이밍 99 | 100 | 101 | # 7. 연산자 102 | **연산자** : 하나 이상의 표현식을 대상으로 산술, 할당, 비교, 논리 등을 수행해 하나의 값을 만듦 103 | **피연산자** : 연산의 대상으로 값으로 평가될 수 있는 표현식 104 | 105 | ## 산술 연산자 106 | 피연산자를 대상으로 수학적 계산을 수행해 새로운 숫자 값 생성 107 | 불가능한 경우 NaN을 반환 108 | 109 | ### 이항 산술 연산자 110 | 2개의 피연산자를 산술 연산해 숫자 값을 계산 111 | 피연산자의 값을 변경하지 않고 새로운 값을 생성 (side effect X) 112 | 113 | ### 단항 산술 연산자 114 | 1개의 피연산자를 산술 연산해 숫자 값을 계산 115 | 116 | 증가/감소 연산자의 경우 다른 산술 연산자와 다르게 기존의 값을 변경 117 | 118 | ## 문자열 연결 연산자 119 | `+` 연산자는 피연산자 중 하나 이상이 문자열인 경우 문자열 연결 연산자로 동작 120 | 이런 경우 다른 피연산자가 문자열이 아니더라도 문자열로 타입 변경 (암묵적 타입 변환) 121 | 122 | ## 할당 연산자 123 | 우항에 있는 피연산자의 평가 결과를 좌항에 있는 변수에 할당 124 | 할당문은 **값으로 평가되는 표현식인 문**으로서 할당된 값으로 평가 125 | -> 값 ⭕️ 표현식 ⭕️ 126 | 127 | ## 비교 연산자 128 | 좌항과 우항의 피연산자 비교 후 결과값을 불리언 값으로 변경 129 | 130 | ### 동등/일치 비교 연산자 131 | 동등 비교(`==`) : 좌항과 우항의 피연산자를 비교할 때 먼저 암묵적 타입 변환을 통해 일치시킨 후 같은 값인지 비교 132 | 일치 비교(`===`) : 좌항과 우항의 피연산자가 타입도 같고 값도 같은 경우에 한하여 true를 반환 133 | 134 | > NaN은 자신과 일치하지 않는 유일한 값으로 일치 비교 연산자에서 주의해야함. 숫자가 NaN인지 조사하기 위해선 Number.isNaN을 사용 135 | 136 | > Object.is 메서드 사용 추천 137 | 138 | ## 삼항 조건 연산자 139 | if...else문과의 가장 큰 차이점은 **값으로 사용 여부** 140 | 삼항 조건 연산자는 값으로 평가할 수 있는 표현식인 문 141 | 142 | ## 논리 연산자 143 | 논리 부정(!) 연산자는 언제나 불리언 값을 반환 144 | 145 | ## 쉼표 연산자 146 | 왼쪽 피연산자부터 차례대로 피연산자를 평가하고 마지막 피연산자의 평가가 끝나면 마지막 피연산자의 평가 결과를 반환 147 | 148 | ## 그룹 연산자 () 149 | 연산자 우선 순위가 가장 높음 150 | 151 | ## typeof 연산자 152 | 피연산자의 데이터 타입을 문자열로 반환 153 | null을 반환하는 함수는 없으며 함수는 function 반환 154 | **typeof 가 반환하는 문자열은 7개의 데이터 타입과 정확히 일치하지 않음** 155 | 156 | **주의할 점** 157 | - typeof null == "object" 158 | - typeof 선언하지 않은 식별자 == undefined 159 | 160 | ## 지수 연산자 161 | 좌항의 피연산자를 밑으로 우항의 피연산자를 지수로 거듭 제곱 162 | 이전에는 `Math.pow()` 사용 163 | 164 | ## 연산자의 부수효과 165 | 다른 코드에 영향을 주는 연산자 166 | - 할당 연산자 (`=`) 167 | - 증가/감소 연산자 (`++`/`--`) 168 | - `delete` 연산자 169 | 170 | ## 연산자 우선 순위 171 | ![](https://i.imgur.com/mHEBgIf.png) 172 | ![](https://i.imgur.com/X6pBV9R.png) 173 | 174 | ## 연산자 결합 순서 175 | ![](https://i.imgur.com/aUl9CY2.png) 176 | ![](https://i.imgur.com/Sho5KtM.png) 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /02) 6. 데이터 타입 & 7. 연산자/saint.md: -------------------------------------------------------------------------------- 1 | ## 6. 데이터 타입 2 | 3 | > 자바스크립트(ES6)는 7개의 데이터 타입을 제공한다. 4 | 5 | ### 원시타입(primitive type) 6 | 7 | 1. Number 8 | 2. String 9 | 3. boolean 10 | 4. undefined 11 | 5. null 12 | 6. Symbol 13 | 14 | ### 객체타입(object/reference type) 15 | 16 | 객체, 함수, 배열 등 17 | 18 | 19 | 20 | ### 원시타입 21 | 22 | #### 1.Number 숫자타입 23 | 24 | 자바스크립트의 숫자 타입은 한 가지. [배정밀도 64비트 부동소수점](https://ko.wikipedia.org/wiki/IEEE_754) 형식을 따르며 모든 수를 `실수`로 처리한다. 25 | 26 | ```jsx 27 | //숫자 타입 28 | var integer = 10; //정수 29 | var double = 10.12; //실수 30 | var negative = -20; //음의 정수 31 | ``` 32 | 33 | `정수로 표시`되어도 사실은 `실수`이기때문에 정수로 표시되는 수끼리 나누더라도 실수가 나올 수 있다. 34 | 35 | ```jsx 36 | //숫자 타입은 모두 실수로 처리된다. 37 | console.log(1===1.0); //true 38 | console.log(4 / 2); //2 39 | console.log(3 / 2;) //1.5 40 | ``` 41 | 42 | 숫자 타입은 추가적으로 세가지 특별한 값도 표현 할 수 있다. 43 | 44 | 📌 Infinity : 양의 무한대 -Infinity : 음의 무한대 NaN : 산술 연산 불가 (not-a-number) 45 | 46 | 47 | 48 | #### 2.String 문자열 타입 49 | 50 | 자바스크립트에서 문자열은 작은따옴표(`''`),큰따옴표(`""`),백틱(````)으로 감싼다. 51 | 52 | ```jsx 53 | //문자열 타입 54 | var string; 55 | string = '문자열'; 56 | string = "문자열"; 57 | string = `문자열`; //(ES6) 58 | string = '작은따옴표로 감싼 문자열 내의 "큰따옴표"는 문자열로 인식된다.'; 59 | string = "큰따옴표로 감싼 문자열 내의 '작은따옴표'는 문자열로 인식된다."; 60 | ``` 61 | 62 | 자바 스크립트의 문자열은 `원시 타입`이며, `변경 불가능한 값 (immutable value)`이다. 63 | 64 | #### 3.boolean 불리언 65 | 66 | 논리적 참,거짓을 나타내는 값. `true` , `false` 67 | 68 | #### 4.undefined 69 | 70 | undefined타입은 `undefined`가 유일. 71 | 72 | 자바스크립트 엔진이 변수를 초기화 할때 사용하는 값. 변수에 값이 없다는 것을 명시하고 싶을때는 `null`을 사용한다. 73 | 74 | #### 5.null 75 | 76 | null타입은 `null`이 유일. 77 | 78 | 프로그래밍 언어에서 null은 **변수에 값이 없다**는 것을 `의도적으로 명시(의도적 부재 intentional absence)`할 때 사용한다. 79 | 80 | #### 6.Symbol 81 | 82 | 다른 값과 `중복 되지 않는` 유일무이한 값. ES6에서 추가되었다. 83 | 84 | ### 객체타입 85 | 86 | #### 7.Object 객체타입 87 | 88 | 자바스크립트를 이루고 있는 거의 모든 것이 객체. 89 | 90 | ------ 91 | 92 | #### 데이터타입의 필요성 93 | 94 | 몇 바이트의 메모리 공간을 사용해야 낭비와 손실 없이 값을 저장할 수 있는지 알아야한다. 95 | 96 | ⇒ `데이터 타입`의 종류에 따라 `크기의 정해진 크기`의 `메모리 공간을 확보`한다. 97 | 98 | - 값을 저장할 때 확보해야 하는 **메모리 공간의 크기**를 결정하기 위해 99 | - 값을 참조할 때 한 번에 읽어 들여야 할 **메모리 공간의 크기**를 결정하기 위해 100 | - 메모리에서 읽어 들인 **2진수를 어떻게 해석**할지 결정하기 위해 101 | 102 | ------ 103 | 104 | #### 동적 타이핑 105 | 106 | 변수를 선언 할때 타입을 선언하지 않고 어떠한 데이터 값이라도 자유롭게 할당 할 수 있다. 107 | 108 | 자바스크립트의 변수는 선언이 아닌 `할당`에 의해 `타입이 결정(타입 추론type inference)`된다. 109 | 110 | `재할당`에 의해 변수의 `타입`은 언제든지 동적으로 변할 수 있다. ⇒ **동적 타이핑 (dynamic typing)** 111 | 112 | 📌 변수는 타입을 갖지 않는다. 값은 타입을 갖는다. 113 | 114 | 115 | 116 | ## 07 연산자 117 | 118 | 연산자는 하나 이상의 표현식을 대상으로 산술, 할당 비교, 논리, 타입, 지수 연산 등을 수행하여 하나의 값을 만든다. 119 | 120 | #### 연산자의 종류 121 | 122 | ```js 123 | // 산술 연산자 124 | 5 * 4 // 20 125 | 126 | // 문자열 연결 연산자 127 | 'My name is' + 'Lee' // 'My nama is Lee' 128 | 129 | // 할당 연산자 130 | color = 'red' // 'red' 131 | 132 | // 비교 연산자 133 | 3 > 5 // false 134 | 135 | // 논리 연산자 136 | true & false // false 137 | 138 | // 타입 연산자 139 | typeof 'Hi' // string 140 | ``` 141 | 142 | 143 | 144 | ### 산술 연산자 : 피연산자를 대상으로 수학적 게산 수행. 산술 연산이 불가능한 경우 NaN 반환 145 | 146 | #### 이항 산술 연산자 : 2개의 피연산자를 산술 연산하여 숫자 값을 만듬 147 | 148 | | 이항 산술 연산자 | 의미 | 부수 효과 | 149 | | :--------------: | :----: | :-------: | 150 | | + | 덧셈 | X | 151 | | - | 뺄셈 | X | 152 | | * | 곱셉 | X | 153 | | / | 나눗셈 | X | 154 | | % | 나머지 | X | 155 | 156 | #### 단항 산술 연산자 157 | 158 | | 단항 산술 연산자 | 의미 | 부수 효과 | 159 | | :--------------: | :--------------------------------------------------: | :-------: | 160 | | ++ | 증가 | O | 161 | | -- | 감소 | O | 162 | | + | 어떠한 효과도 없다. 음수를 양수로 반전하지도 않는다. | X | 163 | | - | 양수를 음수로, 음수를 양수로 반전한 값을 반환한다. | X | 164 | -------------------------------------------------------------------------------- /03) 8. 제어문 & 9. 타입변환과 단축평가/8_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/03) 8. 제어문 & 9. 타입변환과 단축평가/8_1.png -------------------------------------------------------------------------------- /03) 8. 제어문 & 9. 타입변환과 단축평가/8_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/03) 8. 제어문 & 9. 타입변환과 단축평가/8_2.png -------------------------------------------------------------------------------- /03) 8. 제어문 & 9. 타입변환과 단축평가/Dana.md: -------------------------------------------------------------------------------- 1 | # 8. 제어문 2 | 조건에 따라 코드 블록을 실행(조건문)하거나 반복실행(반복문)할 때 사용 3 | 4 | 코드의 실행 흐름을 인위적으로 제어할 수 있기 때문에 가독성을 해칠 수 있다는 단점이 있음. 5 | 이를 보완하기 위해 고차함수를 이용한 함수형 프로그래밍 기법에서 제어문의 사용을 억제하여 복잡성을 해결 6 | 7 | ## 8.1 블록문 (하나의 실행단위) 8 | 0개 이상의 문을 중괄호로 묶은 것으로 코드 블록, 또는 블록이라고 부름 9 | 10 | 자체 종결성을 갖기 때문에 별도로 세미콜론을 붙이지 않아도 됨. 11 | 12 | ## 8.2 조건문 13 | 주어진 조건식의 평가 결과에 따라 코드 블록의 실행을 결정. 14 | * 조건식 : = 불리언 값으로 평가될 수 있는 표현식 15 | 16 | ### 8.2.1 if...else문 17 | 주어진 조건식의 평가 결과에 따라 실행할 블록을 결정 - true : if문 , false : else문 18 | 19 | ```javascript 20 | if (조건식1){ 21 | //조건식1이 참이면 이 코드 블록 실행 22 | //조건식1의 결과값이 불리언 값이 아니더라도 23 | //암묵적으로 불리언 타입으로 타입 변환이 이뤄짐 24 | }else if (조건식2){ 25 | //조건식 1이 참이 아니고 26 | //조건식2이 참이면 이 코드 블록 실행 27 | //여러 else if 사용 가능 28 | }else { 29 | //조건식들이 모두 거짓인 경우 30 | //이 블록문 실행 31 | } 32 | ``` 33 | 34 | 대부분의 조건문은 삼항 조건 연산자로 변경 가능 35 | 삼항 조건 연산자는 **값으로 평가되는 표현식**을 만들기 때문에 변수에 할당할 수 있다는 차이점이 있음 36 | 37 | ```javascript 38 | let even = num === 0 ? '0' : 39 | num % 2 === 0 ? 'even' : 'odd' 40 | ``` 41 | 42 | ### 8.2.2 switch 문 43 | 주어진 표현식을 평가하여 그 값과 일치하는 표현식을 가진 case문으로 실행 흐름을 옮김 44 | 논리적 참,거짓보다 다양한 상황에 따라 실행할 코드 블럭을 결정할 때 사용 45 | 46 | case문은 상황을 의미하는 표현식을 지정하고 콜론으로 마친 뒤, 실행할 문들을 위치시킨다. 47 | 48 | 일치하는 case문이 없다면 실행 순서는 default문으로 이동. default문은 선택사항 49 | 50 | ```javascript 51 | switch(표현식){ 52 | case 표현식1: 53 | // 표현식 == 표현식 1 -> 실행될 문 54 | break; 55 | case 표현식2: 56 | // 표현식 == 표현식 2 -> 실행될 문 57 | break; 58 | default: 59 | // 일치하는 표현식이 없는 경우 실행 60 | } 61 | ``` 62 | 63 | break문을 작성하지 않는 경우, 폴스루 발생 64 | * **폴스루(fall through)** : 표현식의 결과가 일치하는 case문이 있었음에도 switch문을 탈출하지 않고 이후 모든 case문과 default문을 실행하는 경우 65 | 66 | 여러개의 case문을 하나의 조건으로 이용하는 경우 폴스루가 유용하게 사용되기도 함 67 | ```javascript 68 | swich(num){ 69 | case 1: case 3: case 5: case 7: case 9: 70 | numType = 'odd'; 71 | break; 72 | default: 73 | numType = 'even'; 74 | break; 75 | } 76 | ``` 77 | 78 | ## 8.3 반복문 79 | 조건식의 평가 결과가 참인 경우 코드 블록을 실행한다. 그 후 조건식을 다시 평가해 거짓일 때까지 반복 실행한다. 80 | 81 | ### 8.3.1 for문 82 | ```javascript 83 | for(1.변수 선언문 또는 할당문; 2. 조건식; 4. 증감식){ 84 | 3. 조건식이 참인 경우 반복 실행될 문 85 | // 이후 2,3,4 반복 86 | } 87 | ``` 88 | 89 | ### 8.3.2 while문 90 | for문은 반복 횟수가 명확할 때 주로 사용 91 | while문은 반복 횟수가 불명확할 때 주로 사용 92 | 93 | ```javascript 94 | while(조건문){ 95 | //조건문이 항상 참인 경우 무한 루프 발행 96 | //이런 경우엔 탈출 조건을 만들고 break문으로 탈출 97 | //if(탈출 조건) break; 98 | } 99 | ``` 100 | 101 | ### 8.3.3 do...while문 102 | 코드 블록을 먼저 실행하고 조건식을 평가하기 때문에 무조건 한 번 이상 코드 블록 실행 103 | 104 | ## 8.4 break문 105 | 레이블문, 반복문 또는 switch문의 코드 블록을 탈출 106 | 이외에 break 사용시 Syntaxerror 발생 107 | 108 | ### **레이블문** : 식별자가 붙은 문 109 | `fruit : console.log("apple")` 110 | * 프로그램의 실행 순서를 제어하는데 사용 111 | * switch문의 case문과 default문도 레이블문 112 | * **중첩된 for문 내부의 for문에서 외부 for문을 탈출하기 위해** 레이블문 사용 113 | ```javascript 114 | outer : for(var i = 0; i<3 ; i++){ 115 | inner : for(var j=0; j<3; j++){ 116 | if(i+j === 3) break outer; 117 | } 118 | } 119 | ``` 120 | 121 | ## 8.5 continue문 122 | 반복문의 코드 블록 실행을 현 지점에서 중단하고 다음 반복으로 넘어감 123 | 124 | # 9. 타입 변환과 단축 평가 125 | ## 9.1 타입 변환이란? 126 | 자바스크립트의 모든 값은 타입이 존재 127 | 타입은 개발자의 의도에 따라 다른 타입으로 변환이 가능하며 이런 경우 128 | = **명시적 타입 변환** 또는 **타입 캐스팅** 129 | 130 | 이와 반대로 의도와 관계없이 자바스크립트 엔진에 의해 암묵적으로 타입이 변환되는 경우 131 | = **암묵적 타입 변환** 또는 **타입 강제 변환** 132 | 133 | 타입 변환은 기존 원시 값을 직접 변경하는 것은 아님(원시값은 변경 불가능한 값) 134 | 타입 변환은 **기본 원시값을 사용해 다른 타입의 새로운 원시 값을 생성하는 것** 135 | 암묵적 타입 변환은 새로운 원시 값을 한 번 사용하고 버림 136 | 137 | 가장 중요한 건 **예측 가능한 코드**이어야 한다는 것 138 | 139 | ## 9.2 암묵적 타입 변환 140 | 표현식을 평가할 때 코드의 문맥에 부합하지 않는 다양한 상황이 발생할 수 있음. 141 | ```javascript 142 | // 피연산자가 모두 문자열 타입 143 | '10' + 2 // '102' 144 | 145 | // 피연산자가 모두 숫자 타입 146 | 5 * '10' // 50 147 | 148 | // 피연산자 혹은 표현식이 불리언 타입 149 | !0 // true 150 | if(1){} //1은 true로 형변환 151 | ``` 152 | 153 | ### 9.2.1 문자열 타입으로 변환 154 | 자바스크립트 엔진은 문자열 연결 연산자 표현식을 평가하기 위해 문자열 연결 연산자의 피연산자 중 문자열 타입이 아닌 피연산자를 문자열 타입으로 암묵적 타입 변환 155 | 156 | - `숫자` + `문자열` = `문자열` 157 | - `불리언` + `문자열` = `문자열`('true', 'false') 158 | - `null` + `문자열` = `문자열` 159 | - `undefined` + `문자열` = `문자열` 160 | - `Symbol타입` + `문자열` = TypeError 161 | - `객체 타입` + `문자열` = `문자열` 162 | 163 | ### 9.2.2 숫자 타입으로 변환 164 | 산술 연산자의 경우, 숫자값을 만드는 역할을 하기 때문에 문맥상 숫자 타입이 와야함 165 | (+ 산술 연산자는 단항 연산자인 경우만 ex) `+'0' -> 0`) 166 | 167 | 따라서 **산술 연산자의 피연산자들은 숫자 타입으로 타입 변환**이 됨. 168 | 숫자 타입으로 변경할 수 없는 피연산자인 경우 `NaN`을 리턴 169 | 170 | 비교 연산자 역시 불리언 값을 리턴하기 위해선 두 피연산자를 비교해야하므로 피연산자는 숫자 타입이어야 함. 171 | 172 | - `+문자열(숫자)` = `숫자` 173 | - `+문자열(문자)` = `NaN` 174 | - `+불리언` = true -> `1` , false -> `0` 175 | - `+null` = `0` 176 | - `+undefined` = `NaN` 177 | - `+Symbol()` = TypeError 178 | - `+객체` = `NaN` 179 | - 예외) 빈 문자열('')과 빈 배열([])은 0으로 치환 180 | 181 | ### 9.2.3 불리언 타입으로 변환 182 | 제어문 또는 조건식은 불리언 값으로 평가되어야 하는 표현식 183 | 184 | 자바스트립트 엔진은 불리언타입이 아닌 값을 Truthy값 또는 Falsy값으로 구분 185 | 186 | > Falsy값 187 | > - false 188 | > - undefined 189 | > - null 190 | > - 0, -0 191 | > - NaN 192 | > - ''(빈 문자열) 193 | 194 | ## 9.3 명시적 타입 변환 195 | ### 9.3.1 문자열 타입으로 변한 196 | 1. String 생성자 함수를 new 연산자 없이 호출하는 방법 197 | - `String('Infinity')` -> "Infinity" 198 | 2. Object.prototype.toString 메서드를 사용하는 방법 199 | - `(Infinity).toString()` -> "Infinity" 200 | 3. 문자열 연결 연산자를 이용하는 방법 201 | - `Infinity + ''` -> "Infinity" 202 | 203 | ### 9.3.2 숫자 타입으로 변환 204 | 1. Number 생성자 함수를 new 연산자 없이 호출하는 방법 205 | - `Number('0')` -> 0 206 | 2. parseInt, parseFloat 함수를 사용하는 방법 (문자열만 숫자 타입으로 변환 가능) 207 | - `parseInt('0')` -> 0 208 | 3. `+` 단항 산술 연산자를 이용하는 방법 209 | - `+'0'` -> 0 210 | 4. `*` 산술 연산자를 이용하는 방법 211 | - `0 * 1` -> 0 212 | 213 | ### 9.3.3 불리언 타입으로 변환 214 | 1. Boolean 생성자 함수를 new 연산자 없이 호출하는 방법 215 | - `Boolean('x')` -> true 216 | 2. ! 부정 논리 연산자를 두번 사용하는 방법 217 | - `!!{}` -> true 218 | - `!![]` -> true 219 | 220 | ## 9.4 단축 평가 221 | ### 9.4.1 논리 연산자를 사용한 단축 평가 222 | 논리합(||) 또는 논리곱(&&) 연산자 표현식은 언제나 2개의 피연산자 중 어느 한쪽으로 평가됨 223 | 이 때 논리 연산의 결과를 결정하는 피연산자를 타입 변환하지 않고 그대로 반환 = **단축 평가** 224 | 표현식을 평가하는 도중에 평가 결과가 확정된 경우 나머지 평가 과정을 생략하는 것 225 | 226 | |단축 평가 표현식 | 평가 결과 | 227 | |-----|----| 228 | |`true \|\| anything` | true | 229 | |`false \|\| anything` | anything | 230 | |`true && anything` | anything | 231 | |`false && anything` | false | 232 | 233 | #### 단축 평가가 유용한 상황 234 | - 객체를 가리키기를 기대하는 변수가 null 또는 undefined가 아닌지 확인하고 프로퍼티를 참조할 때 235 | `let value = item && item.value` 236 | - 함수 매개변수에 기본값을 설정할 때 237 | ```javascript 238 | function func1 (arg) { 239 | arg = arg || '' // 해당 값이 undefined인 경우 기본 값 설정 240 | } 241 | ``` 242 | 243 | ### 9.4.2 옵셔널 체이닝 연산자 (?.) 244 | 좌항의 피연산자가 null 또는 undefined인 경우 undefined를 반환 245 | 그렇지 않는 경우 프로퍼티 참조를 이어감 246 | 247 | > && 로 연산하는 방법도 있지만 0이나 ''는 비어있는 값임에도 객체로 평가되는 경우가 있기때문에 별도로 체크하는 과정이 필요함 248 | ![](https://i.imgur.com/MmWtYqk.png) 249 | 250 | 따라서 정확성을 위해 객체를 가리키기를 기대하는 변수가 null 또는 undefined가 아닌지 확인하고 프로퍼티를 참조할 때 옵셔널 체이닝을 이용하는 것을 권장 251 | 252 | ### 9.4.3 null 병합 연산자 253 | 좌항의 피연산자가 null 또는 undefined인 경우 우항의 연산자를 반환 254 | 그렇지 않으면 피연산자를 반환 255 | 변수에 기본값을 설정할 때 유용 256 | 257 | 논리연산자의 경우 모든 falsy 값을 걸러내기 때문에 의도적으로 falsy값을 넣는 경우 (0,'' 등) 예기치 못한 동작이 발생할 수 있음. 258 | -------------------------------------------------------------------------------- /03) 8. 제어문 & 9. 타입변환과 단축평가/June.md: -------------------------------------------------------------------------------- 1 | # 8. 제어문 2 | 3 | > 제어문은 조건에 따라 코드 블록을 실행하거나 반복 실행할 때 사용한다. 4 | 5 | ## 8.1 블록문 6 | 7 | > 블록문은 0개 이상의 문을 중괄호로 묶은 것으로, 코드 블록 또는 블록이라고 부르기도 한다. 8 | 9 | 원래 문 끝에서는 세미콜론을 붙이는 게 일반적인데, 블록문은 문의 종료를 의미하는 자체 종결성을 갖기 때문에 세미콜론을 붙이지 않는다. 10 | 11 | ```javascript 12 | // 블록문 13 | { 14 | const hi = "hi"; 15 | } 16 | 17 | // 제어문 18 | let hi = "hi"; 19 | if (hi !== "hi") { 20 | hi = "hello"; 21 | } 22 | 23 | // 함수 선언문 24 | function sum(a, b) { 25 | return a + b; 26 | } 27 | ``` 28 | 29 | ## 8.2 조건문 30 | 31 | ### 8.2.1 if - else문 32 | 33 | ```javascript 34 | // if - else문 35 | if (조건식) { 36 | ... 37 | } else { 38 | ... 39 | } 40 | 41 | // if - else if - else 문 42 | if (조건식) { 43 | ... 44 | } else if (조건식) { 45 | ... 46 | } else { 47 | ... 48 | } 49 | 50 | // 보통 if - else 문은 3항연산자로 바꿔쓸 수 있다. 51 | let result = ""; 52 | if (조건식) { 53 | result = "good"; 54 | } else { 55 | result = "bad"; 56 | } 57 | 58 | result = 조건식 ? "good" : "bad"; 59 | ``` 60 | 61 | ### 8.2.2 switch문 62 | 63 | ```javascript 64 | switch (표현식) { 65 | case 표현식1: 66 | // 표현식과 표현식1이 일치하면 실행될 문; 67 | break; 68 | case 표현식2: 69 | // 표현식과 표현식1이 일치하면 실행될 문; 70 | break; 71 | default: 72 | // 표현식과 일치하는 case문이 없을 때 실행될 문; 73 | } 74 | ``` 75 | 76 | - `break`문을 써주지 않으면 의도치 않은 결과가 나올 수 있다. 77 | - `default`뒤에는 `break`를 쓰지 않는다. (어차피 switch문이 끝나니까) 78 | - `if - else`로 처리할 수 있으면 처리하는 게 낫고, 조건이 너무 많을 때는 `switch`를 사용하자. 79 | 80 | ## 8.3 반복문 81 | 82 | - 반복문은 조건식의 평가 결과가 참인 경우 코드 블록을 실행한다. 조건식을 다시 평가하여 여전히 참인 경우 코드 블록을 다시 실행한다. 이는 조건식이 거짓일 때 까지 반복된다. 83 | 84 | - 자바스크립트는 세 가지 반복문인 `for`, `while`, `do...while`을 제공한다. 85 | 86 | - 배열을 순회할 때는 `forEach` 87 | - 객체의 프로퍼티를 열거할 때는 `for...in` 88 | - 이터러블을 순회할 수 있는 `for...of` 89 | - 이 처럼 자바스크립트에서 반복문을 대체할 수 있는 다양한 기능을 제공한다. 90 | 91 | ## 8.4 break문 92 | 93 | - `break`문은 코드 블록을 탈출한다. 94 | - 레이블 문, 반복문, switch문 이외에는 `break`를 사용하면 문법 에러가 발생한다. 95 | 96 | ```javascript 97 | // foo라는 레이블 식별자가 붙은 레이블 문 98 | foo: console.log("foo"); 99 | ``` 100 | 101 | - 중첩된 for문을 빠져나가고 싶을 때는 레이블 문을 사용하면 된다. 102 | 103 | ```javascript 104 | // outer라는 식별자를 가진 레이블 for 문 생성 105 | outer: for (let i = 0; i < 2; i++) { 106 | for (let j = 0; j < 2; j++) { 107 | // i + j가 2이면 바깥의 for문을 빠져나간다. 108 | if (i + j === 2) break outer; 109 | console.log(`${i}, ${j}`); 110 | } 111 | } 112 | ``` 113 | 114 | - 근데 위의 레이블문은 위의 예시 이외에는 별로 권장되지 않는다. 115 | - 가독성이 떨어지고, 오류를 발생시킬 가능성이 높아진다. 116 | 117 | ## 8.5 continue문 118 | 119 | - continue문은 반복문의 코드 블록 실행을 현 지점에서 중단하고, 반복문의 증감식으로 실행 흐름을 이동시킨다. break 문처럼 반복문을 탈출하지는 않는다. 120 | 121 | # 9. 타입 변환과 단축 평가 122 | 123 | ## 9.1 타입 변환이란? 124 | 125 | - 자바스크립트에의 모든 값에는 타입이 있는데 개발자가 의도적으로 타입을 변환하는 것을 **명시적 타입 변환** 또는 **타입 캐스팅** 이라고 한다. 126 | - 개발자가 의도적으로 변환하는 게 아니라 자바스크립트 엔진에 의해 변환되는 것을 **암묵적 타입 변환** 또는 **타입 강제 변환**이라 한다. 127 | - 타입 변환이 기존 원시 값을 직접 변경하는 것은 아니다. 원시 값은 변경 불가능한 값이므로 변경할 수 없다. 128 | - 명시적 타입 변환은 개발자가 대놓고 변환해서 알아보기 그나마 쉬운데, 암묵적으로 변할 때는 우리가 예측할 수 있어야한다. 129 | 130 | ### 9.2.3 불리언 타입으로 변환 131 | 132 | - `Falsy`: false로 판단되는 값 133 | - false, undefined, null, 0, -0, NaN, ''(빈 문자열) 134 | - `Truthy`: true로 판단되는 값 135 | - `Falsy` 이외에는 전부 true로 판별된다. 136 | 137 | ## 9.3 명시적 타입 변환 138 | 139 | ### 9.3.1 문자열 타입 변환 140 | 141 | - String(), ''.toString() 142 | - 혹은 문자열 연결 연산자 `+`를 이용해 암묵적 타입 변환 143 | 144 | ### 9.3.2 숫자 타입으로 변환 145 | 146 | - Number(), parseInt(), parseFloat() 147 | - +'0' 와 같이 단항 산술 연산자를 이용해 암묵적으로 변환 148 | - \*'0' 와 같이 암묵적으로 변환 149 | 150 | ### 9.3.3 불리언 타입으로 변환 151 | 152 | - Boolean() 153 | - !!x 처럼 부정 논리 연산자를 두 번 사용 154 | 155 | ## 9.4 단축 평가 156 | 157 | ### 9.4.1 논리 연산자를 사용한 단축 평가 158 | 159 | - && 논리곱 연산자는 두 개의 피연산자가 모두 true로 평가될 때 true를 반환 160 | - || 논리합 연산자는 둘 중 하나만 true로 평가되어도 true를 반환 161 | 162 | ```javascript 163 | true || anything; // true 164 | false || anything; // anything 165 | true && anything; // anything 166 | false && anything; // false 167 | ``` 168 | 169 | ### 9.4.2 옵셔널 체이닝 연산자 170 | 171 | - ECMAScript2020에 도입 172 | - 옵셔널 체이닝 연산자 `?`는 좌항의 피연산자가 null 또는 undefined일 경우 undefined를 반환하고, 그렇지 않으면 우항의 프로퍼티 참조를 이어간다. 173 | 174 | ```javascript 175 | var hyeonsu = "hyeonsu"; 176 | 177 | var value = hyeonsu?.old; 178 | console.log(value); // undefined; 179 | ``` 180 | 181 | ### 9.4.3 null 병합 연산자 182 | 183 | - ECMAScript2020에 도입 184 | - 좌항의 피연산자가 null 또는 undefined인 경우 우항의 피연산자를 반환하고, 그렇지 않으면 좌항의 피연산자를 반환한다. 기본값 설정에 유용하다. 185 | 186 | ```javascript 187 | var foo = null ? 'default string'; 188 | console.log(foo) // default string 189 | ``` 190 | -------------------------------------------------------------------------------- /03) 8. 제어문 & 9. 타입변환과 단축평가/README.md: -------------------------------------------------------------------------------- 1 | # 8. 제어문 & 9. 타입변환과 단축평가 2 | 3 | ## 정리 4 | 5 | - [춘식]() 6 | - [뽀송]() 7 | - [세인트 - 메인 발표자](./saint.md) 8 | - [이안]() 9 | - [준]() 10 | - [다나]() 11 | -------------------------------------------------------------------------------- /03) 8. 제어문 & 9. 타입변환과 단축평가/ayaan.md: -------------------------------------------------------------------------------- 1 | ## 8장 제어문 2 | 3 | 제어문을 사용하면 코드의 실행 흐름을 인위적으로 제어할 수 있다. 하지만 코드의 실행 순서가 변경된다는 것은 단순히 위에서 아래로 순차적으로 진행하는 직관적인 코드의 흐름을 혼란스럽게 만든다. 따라서 제어문을 사용하면 코드의 흐름을 해치기 때문에 가독성이 떨어질 수도 있는 단점이 있다. 물론 고차 함수(map, filter, forEach)등으로 제어문의 사용을 억제하여 복잡성을 해결할 수 있다. 하지만 이번 장에서는 고차 함수가 아닌 제어문을 바르게 이해하기 위해 for 문을 다룬다. 4 | 5 |
6 | 7 | ## 8.1 블록문 8 | 9 | 블록문은 0개 이상의 문을 중괄호로 묶은 것으로 코드 블럭이라고도 부른다. 그리고 자바스크립트는 이 블록문을 하나의 실행 단위로 취급한다. 그리고 주의해야 할 점은 보통 문의 끝에는 세미콜론을 붙이지만, 블록문은 자체만으로 종결성을 갖기 때문에 블록문의 끝에는 세미콜론을 붙이지 않는다. 10 | 11 |
12 | 13 | ## 8.2 조건문 14 | 15 | 조건문은 평과 결과에 따라 코드 블럭의 실행을 결정한다. 그리고 조건문안에 조건식은 불리언 값으로 평가될 수 있는 표현식이다. 자바스크립트에서는 if...else문과 switch문 두 가지 조건문을 제공한다. 16 | 17 | ```js 18 | const num = 2; 19 | if (num > 0) { 20 | // 조건식이 참이면 이 코드 블럭 실행 => 양수 21 | } else if (num < 0) { 22 | // 조건식이 거짓이면 이 코드 블럭 실행 => 음수 23 | } else { 24 | // 조건식, 조건식2가 거짓이면 이 코드 블럭 실행 => 숫자 영 25 | } 26 | ``` 27 | 28 | 위 부분은 삼항 연산자로도 표현할 수 있다. 29 | 30 | ```js 31 | const num = 2; 32 | const study = num ? (num > 0 ? "양수" : "음수") : "숫자 영"; 33 | ``` 34 | 35 | 하지만 조건에 따라 실행해야 할 내용이 복잡하여 여러 줄의 문이 필요하다면 if...else문이 가독성에 더 좋다고 책에서 설명하고 있다. 당장 위에 있는 코드만 보더라도 삼항 연산자는 가독성이 떨어진다. 개인적인 생각으로는 적어도 3개의 조건식이 필요하다면 if...else문을 사용하는 것이 좋다고 생각한다. 36 | 37 | 다음으로는 switch문이다. switch문의 표현식은 불리언 값보다는 문자열이나 숫자 값인 경우가 많다. 다시 말해, if...else문은 논리적인 참, 거짓으로 결정하고 switch는 다양한 상황(case)에 따라 실행할 코드 블럭을 결정한다. 38 | 39 | ```js 40 | switch (표현식) { 41 | case 표현식1: 42 | // 표현식 === 표현식1일 때 실행 43 | break; 44 | case 표현식2: 45 | // 표현식 === 표현식2일 때 실행 46 | break; 47 | default: 48 | // 표현식이 표현식1, 표현식2랑 일치하는 게 없을 때 실행 49 | // default 에서는 break를 사용하지 않음 50 | } 51 | ``` 52 | 53 |
54 | 55 | ## 8.3 반복문 56 | 57 | 자바스크립트 반복문에는 for문, while문, do...while문 등이 있다. 그리고 반복문을 대체할 수 있는 기능으로는 forEach 메서드, 객체의 프로퍼티를 열거할 때 사용하는 for...in문, ES6에서 도입된 이터러블을 순회할 수 있는 for...of문 등이 있다. 58 | 59 |
60 | 61 | ## 9장 타입변환과 단축 평가 62 | 63 | 자바스크립트의 모든 값은 타입이 있다. 그리고 개발자가 의도적으로 타입을 변환하는 것을 명시적 타입 변환 또는 타입 캐스팅이라고 한다. 64 | 65 | ```js 66 | const num = 10; 67 | 68 | const str = num.toString(); 69 | // or String(num) 70 | 71 | console.log(typeof str); // string 72 | console.log(typeof num); // number 73 | ``` 74 | 75 | 그리고 개발자의 의도와 상관없이 타입이 변하는 것을 암묵적 타입 변환 또는 타입 강제 변환이라고 한다. 76 | 77 | ```js 78 | const num = 10; 79 | const str = num + ""; 80 | 81 | console.log(typeof str, str); // string "10" 82 | console.log(typeof num); // number 83 | ``` 84 | 85 | 타입 변환이란 기존 원시 값을 사용해 다른 타입의 새로운 원시 값을 생성하는 것이다. 그래서 위의 코드에서 num + ""을 평가하기 위해 str에 num을 재할당하는 것이 아니라 num 자체를 암묵적 타입 변환을 통해 "10"으로 만든다. 그리고 자바스크립트는 "10" + ""을 평가하는 것이다. 그리고 평가 후 암묵적 타입 변환으로 사용된 "10"을 저장하고 그 어디에도 저장하지 않고 num의 값은 버려진다. 86 | 87 | 그렇다면 명시적 타입 변환만을 사용하고(개발자의 의도가 담긴 타입 변환) 암묵적 타입 변환은 사용하면 안되는 걸까? 책에서 나온 대로 암묵적 타입 변환이 가독성 측면에서 더 좋을 수도 있다. 다만 중요한 것은 코드를 예측할 수 있게 개발해야 한다는 것이다. 결국 이러한 코드 작성법은 동료가 정확히 이해할 수 있는 좋은 코드를 작성하기 위한 방법이라고 생각한다. 88 | -------------------------------------------------------------------------------- /03) 8. 제어문 & 9. 타입변환과 단축평가/choonsik.md: -------------------------------------------------------------------------------- 1 | # 8장 제어문 & 9장 타입변환과 단축평가 2 | 3 | ## 8장 제어문 4 | 5 | > 코드의 실행 흐름을 인위적으로 제어하는 문 6 | 7 | ### 8.1 블록문 8 | 9 | **0개 이상의 문을 중괄호로 묶은 것** 10 | 11 | 자바스크립트는 블록문을 하나의 `실행 단위`로 취급한다. 12 | 13 | ### 8.2 조건문 14 | 15 | #### if ... else문 16 | 17 | 불리언 값으로 평가되어야 한다. 18 | 대부분의 `if ...else 문`은 `삼항 조건 연산자`로 바꿔 쓸 수 있다. 19 | 20 | > 값을 결정하느냐, 여러 줄의 문을 실행하느냐에 따라 적절히 골라 쓰자. 21 | 22 | #### switch 문 23 | 24 | 주어진 표현식을 평가하여 그 값과 일치하는 표현식을 갖는 `case 문`으로 실행 흐름을 옮긴다. 25 | 26 | > 폴스루(fall through) 27 | > case 문마다 마지막에 break 문을 사용해야 연이은 재할당이 일어나지 않는다. 28 | > default 문을 마지막에 위치하므로 break 문을 생략하는 것이 일반적이다. 29 | 30 | ### 8.3 반복문 31 | 32 | 조건식의 평가 결과가 참인 경우 코드 블록을 실행한다. 33 | 34 | `for`, `while`, `do ...while` 문이 있다. 35 | 36 | `forEach`(배열 순회), `for ...in`(객체 프로퍼티 열거), `for ...of`(이터러블 순회) 등의 문으로 대체할 수 있다. 37 | 38 | ### 8.4 break 문 39 | 40 | 레이블 문(식별자가 붙은 문), 반복문, switch 문의 코드 블록을 탈출한다. 41 | 그 외에서는 `SyntaxError`가 발생한다. 42 | 43 | ```js 44 | foo: { 45 | console.log(1); 46 | break foo; 47 | console.log(2); 48 | } 49 | ``` 50 | 51 | **유용한 예시** 52 | 53 | ```js 54 | outer: for (var i = 0; i < 3; i++) { 55 | for (var j = 0; j < 3; j++) { 56 | if (i + j === 3) break outer; 57 | console.log(`inner [${i}, ${j}]`); 58 | } 59 | } 60 | ``` 61 | 62 | ### 8.5 continue 문 63 | 64 | 반목문의 증감식으로 실행 흐름을 이동시킨다. 65 | 66 |
67 | 68 | ## 09장 타입변환과 단축평가 69 | 70 | ### 9.1 타입 변환이란? 71 | 72 | 개발자가 의도적으로 값의 타입을 변환하는 **명시적 타입 변환** 또는 **타입 캐스팅** 73 | 74 | 자바스크립트 엔진에 의해 암묵적으로 타입이 타동 변환되는 **암시적 타입 변환** 또는 **타입 강제 변환** 75 | 76 | > 원시 값은 변경 불가능하다. 타입 변환이란 기존 원시 값을 사용해 다른 타입의 새로운 원시 값을 생성하는 것이다. 77 | 78 | **중요한 것은 코드를 예측 가느하게 작성하는 것** 79 | 80 | ### 9.2 암묵적 타입 변환 81 | 82 | #### 문자열 타입으로 변환 83 | 84 | \+ 연산자는 피연산자 중 하나 이상이 문자열일 때 문자열 연결 연산자로 동작해 문자열 값을 만든다. 85 | 86 | #### 숫자 타입으로 변환 87 | 88 | \+ 단항 연산자와 산술 연산자는 숫자 값을 만든다. 89 | **만들 수 없는 경우 NaN이 된다.** 90 | 91 | 비교 연산자는 숫자 타입이 아닌 피연산자를 숫자 타입으로 암묵적 타입 변환해 불리언 값을 만든다. 92 | 93 | #### 불리언 타입으로 변환 94 | 95 | > 자바스크립트 엔진은 불리언 타입이 아닌 값을 Truthy(참으로 평가되는 값) 또는 Falsy(거짓으로 평가되는 값)으로 구분한다. 96 | 97 | **Falsy : false, undefined, null, 0, -1, NaN, ''** 98 | 99 | 조건식의 평가 결과를 불리언 타입으로 암묵적 타입 변환한다. 100 | 101 | ### 9.3 명시적 타입 변환 102 | 103 | 1. 표준 빌트인 생성자 함수(String, Number, Boolean)를 new 연산자 없이 호출하기 104 | 105 | 2. 빌트인 메서드 이용하기 106 | 107 | #### 문자열 타입으로 변환 108 | 109 | 1. String() 110 | 2. Object.prototype.toString() 111 | 3. 문자열 연결 연산자 112 | 113 | #### 숫자 타입으로 변환 114 | 115 | 1. Number() 116 | 2. parseInt(), parseFloat() // 문자열만 가능 117 | 3. - 단항 산술 연산자 118 | 4. - 산술 연산자 119 | 120 | #### 불리언 타입으로 변환 121 | 122 | 1. Boolean() 123 | 2. !! 124 | 125 | ### 9.4 단축 평가 126 | 127 | #### 논리 연산자를 사용한 단축 평가 128 | 129 | 논리합(||) 또는 논리곱(&&) 연산자 표현식은 2개의 피연산자 중 어느 한쪽으로 평가된다. 130 | 131 | 1. 논리곱: 모두 true일 때 좌항에서 우항으로 평가 132 | 2. 논리합: 좌항이 true면 좌항 평가 후 종료. 좌항 false, 우항이 true면 우항 반환 133 | 134 | > 단축 평가 135 | > 이처럼 피연산자를 타입 변환하지 않고 그대로 반환하는 것 136 | > if 문을 대체할 수 있다. 137 | 138 | 다음과 같은 경우 유용하다. 139 | 140 | 1. 객체를 가리키기를 기다하는 변수가 null 또는 undefined인지 확인하고 프로퍼티를 참조할 때 141 | 2. 함수 매개변수에 기본값을 설정할 때 142 | 143 | #### 옵셔널 체이닝 연산자 144 | 145 | ?.는 좌항의 피연산자가 null 또는 undefined인 경우 undefined를 반환하고 아니라면 우항의 프로퍼티 참조를 이어간다. 146 | 147 | #### null 병합 연산자 148 | 149 | ??는 좌항의 피연산자가 null 또는 undefined인 경우 우항의 피연산자를 반환하고 그렇지 않으면 좌항의 피연산자를 반환한다. 기본값 설정에 유용하다. 150 | -------------------------------------------------------------------------------- /04) 10. 객체 리터럴 & 11. 원시값과 객체의 비교/Dana.md: -------------------------------------------------------------------------------- 1 | # 10. 객체 리터럴 2 | ## 10.1 객체란? 3 | 자바스크립트는 객체 기반 프로그래밍 언어 4 | 원시 값을 제외한 나머지 값은 모두 객체 5 | 6 | | 원시타입 | 객체타입 | 7 | |-------|-------| 8 | |단 하나의 값 | 다양한 타입의 값을 하나의 단위로 구성한 복합적인 자료구조| 9 | |변경 불가능 | 변경 가능한 값 | 10 | 11 | 자바스크립트에서 사용할 수 있는 모든 값 = `프로퍼티 값` 12 | - 일급 객체인 함수 포함 13 | - 프로퍼티 값이 함수인 경우 = 메서드 14 | 15 | **객체** = 프로퍼티 + 메서드 16 | 0개 이상의 프로퍼티로 구성된 집합 17 | * 프로퍼티 : 키와 값으로 구성되며, 객체의 상태를 나타내는 값(data) 18 | * 메서드 : 프로퍼티를 참조하고 조작할 수 있는 동작 19 | 20 | ## 10.2 객체 리터럴에 의한 객체 생성 21 | 클래스 기반 객체지향 언어 22 | - 클래스를 사전에 정의, 필요한 시점에 **new 연산자와 함께 생성자를 호출**해 인스턴스 생성하는 방식으로 객체 생성 23 | - C++, Java 24 | 25 | > #### 인스턴스 26 | > 클래스에 의해 생성되어 메모리에 저장된 실체 27 | > 객체 지향 프로그래밍에서의 객체 = 클래스 + 인스턴스 28 | > 클래스는 인스턴스를 생성하기 위한 템플릿 역할 29 | 30 | 프로토타입 기반 객체지향 언어 31 | - 다양한 객체 생성 방법 지원 32 | - 객체 리터럴 -> 가장 일반적이고 간단한 방법 33 | - Object 생성자 함수 34 | - 생성자 함수 35 | - Object.create 메서드 36 | - 클래스 37 | - JavaScript 38 | 39 | ### 객체 리터럴 40 | 리터럴 : 사람이 이해할 수 있는 문자 또는 약속된 기호를 사용해 값을 생성하는 표기법 41 | 42 | 객체 리터럴 : {} 를 이용해 0개 이상의 프로퍼티를 정의하며 객체를 생성하는 방법 43 | 변수가 할당되는 시점에 자바스크립트 엔진은 객체 리터럴을 해석해 객체를 생성 44 | 객체 리터럴의 중괄호 !== 코드 블록 -> 자체 종결성 X 세미콜론을 붙여줘야 함. 45 | 46 | 객체 리터럴을 제외한 객체 생성 방식은 모두 함수를 사용해 객체를 생성 47 | 48 | ## 10.3 프로퍼티 49 | 프로퍼티 키 : 빈 문자열을 포함하는 모든 문자열 또는 심벌 값 50 | - 식별자 네이밍 규칙을 따르지 않는 이름에는 반드시 따옴표를 사용해야 함 51 | - `minjuKim : 15 ✅` 52 | - `minju kim : 15 ❌` 53 | - `"minju-kim" : 15 ✅` 54 | - 동적으로 생성하기 위해선 대괄호 사용 55 | - `obj[key] = minju // key = kim 이라는 변수일 때 {kim : minju} 객체 생성` 56 | - 문자열이나 심벌 값 이외의 값을 사용하면 암묵적 타입 변환을 통해 문자열로 치환 57 | - 예약어를 사용할 수 있으나 권장되지 않음 58 | - 이미 존재하는 키를 중복 선언시, 나중에 선언한 키가 이전 키의 값을 덮어씀 59 | 60 | 프로퍼티 값 : 자바스크립트에서 사용할 수 있는 모든 값 61 | 62 | 프로퍼티는 쉼표로 구분 63 | 64 | ## 10.5 프로퍼티 접근 65 | 프로퍼티에 접근하는 방법 66 | 1. 마침표 프로퍼티 접근 연산자(.) : 마침표 표기법 67 | 2. 대괄호 프로퍼티 접근 연산자([]) : 대괄호 표기법 68 | * 대괄호 안에 들어가는 키는 무조건 따옴표로 감싸줘야함 69 | * 감싸지 않고 참조하는 경우 식별자로 해석 70 | 71 | 객체에 존재하지 않는 프로퍼티 접근 시 `undefined` 반환 72 | 73 | 프로퍼티 키가 식별자 네이밍 규칙을 준수하는 경우 74 | -> 두 표기법 모두 사용 가능 75 | -> 아닌 경우, 대괄호 표기법만 사용 가능 (숫자로 이뤄진 문자열인 경우 제외) 76 | ```javascript 77 | ❌ 78 | person.1 79 | person.'1' 80 | 81 | ✅ 82 | person.[1] 83 | person.['1'] 84 | ``` 85 | 86 | > #### person.last-name 87 | > node.js -> ReferenceError 88 | > 브라우저 -> NaN (혹은 window 프로퍼티에 저장된 name 값) 89 | > person.last-name의 변수에 따옴표가 없는 경우, person 객체의 프로퍼티인 last에서 name이라는 변수를 빼는 코드(person.last - name)로 해석됨. 90 | > person.last 라는 객체가 없다면 undefined를 리턴하고, name이라는 변수를 찾기 시작함 91 | > 이 때, node환경에서는 name이라는 변수가 없으니 에러가 발생하지만 92 | > 브라우저 환경에서는 window객체에 name이라는 프로퍼티가 존재 93 | > 해당 프로퍼티는 문자열이지만 - 숫자 연산자를 사용했으니 name 변수는 암묵적으로 숫자형으로 치환 - 하지만 숫자데이터가 아니니 결과값으로 NaN 출력 94 | 95 | ## 10.6 프로퍼티 값 갱신 96 | 이미 존재하는 프로퍼티에 값 할당 -> 값 갱신 97 | 98 | ## 10.7 프로퍼티 동적 생성 99 | 존재하지 않는 프로퍼티에 값을 할당 -> 동적으로 프로퍼티 생성 100 | 101 | ## 10.8 프로퍼티 삭제 102 | delete 연산자를 이용해 프로퍼티 삭제 가능 103 | ```javascript 104 | let person = { 105 | name : "minju" 106 | } 107 | 108 | console.log(person.name) //minju 109 | 110 | delete person.name; 111 | 112 | console.log(person.name) // undefined 113 | ``` 114 | 115 | ## 10.9 ES6에서 추가된 객체 리터럴의 확장 가능 116 | ### 10.9.1 프로퍼티 축약 표현 117 | ES6에서는 프로퍼티 값으로 변수를 사용하는 경우, 변수 이름과 프로퍼티 키가 동일한 이름일 때 키를 생략할 수 있음 118 | ```javascript 119 | let x = 1, y = 2; 120 | 121 | const obj = {x, y}; 122 | 123 | console.log(obj) // {x : 1, y : 2}; 124 | ``` 125 | 126 | ### 10.9.2 계산된 프로퍼티 이름 127 | 프로퍼티 키를 동적으로 생성하기 위해서 128 | - 표현식을 대괄호로 묶기 129 | - 문자열 또는 문자열 타입으로 변환 가능해야함 130 | 131 | ```javascript= 132 | let i = 0; 133 | 134 | obj["serial-" + ++i] = i; // es5 135 | obj[`serial-${++i}`] = i; // es6 136 | 137 | ``` 138 | 139 | ### 10.9.3 메서드 축약 표현 140 | ```javascript= 141 | 142 | let obj = { 143 | func1 : function() { 144 | console.log("es5 grammar") 145 | } 146 | func2() { 147 | console.log("es6 grammar") 148 | } 149 | } 150 | ``` 151 | 위 예시처럼 es6 문법에서는 메서드를 축약형으로 할당 가능함. 152 | 이렇게 선언한 문법은 es5에서 프로퍼티에 함수를 할당하는 방식과 다르게 동작 153 | 154 | # 11. 원시 값과 객체의 비교 155 | | 원시 타입 | 객체 타입 | 156 | |------|------| 157 | |변경 불가능한 값 | 변경 가능한 값 | 158 | |실제 값이 저장 | 참조값이 저장 | 159 | |다른 변수에 할당 시 원시 값이 복사되어 저장 | 참조값이 복사되어 저장 | 160 | |값에 의한 전달 | 참조에 의한 전달 | 161 | 162 | ## 11.1 원시 값 163 | ### 11.1.1 변경 불가능한 값 164 | 한 번 생성된 원시값은 **읽기 전용 값으로 변경될 수 없음** 165 | 166 | 변수 값 변경의 의미 167 | 1. 원시 값을 재할당 168 | 2. 새로운 메모리 공간을 확보하고 재할당한 값을 저장 169 | 3. 변수가 참조하던 메모리 공간의 주소가 바뀜 (불변성) 170 | 따라서, 불변성을 갖는 원시 값을 할당한 변수는 재할당 이외에 변수 값을 변경할 수 있는 방법이 없음. 171 | 172 | ### 11.1.2 문자열과 불변성 173 | 원시 값을 저장하려면 확보해야 하는 메모리 공간의 크기를 결정해야 함 174 | 문자열은 다른 원시값과 달리 문자열이 구성된 문자의 갯수에 따라 메모리 공간의 크기가 결정됨. -> 자바스크립트는 개발자의 편의를 위해 원시 타입의 문자열 타입 제공 175 | 176 | 문자열은 유사배열객체이면서 이터러블 -> 배열과 유사하게 접근 가능 177 | 하지만 원본 데이터를 변경하는 것은 안됨 (재할당은 가능) 178 | 179 | > #### 유사배열객체 180 | > - 배열처럼 인덱스로 접근 가능 181 | > - length 프로퍼티를 가짐 182 | 183 | ### 11.1.3 값에 의한 전달 184 | 변수에 원시값을 갖는 변수를 할당 185 | -> 할당받는 변수에는 **할당되는 변수의 원시 값이 복사**되어 전달 186 | = 값에 의한 전달 187 | 188 | > 같은 값을 가지더라도 다른 메모리 공간에 저장된 별개의 값...? 189 | > 같은 원시값을 참조하다가 한 변수에 재할당이 이뤄지면 새로운 메모리 공간에 재할당된 값 참조...? 190 | 191 | 변수에는 값이 전달되는 것이 아닌 **메모리 주소가 전달** 192 | 식별자 = 메모리 주소에 붙인 이름 193 | 전달된 메모리 주소를 통해 메모리 공간에 접근해 값을 참조하는 방식 194 | 195 | 두 변수의 원시값은 서로 다른 메모리 공간에 저장된 별개의 값이 되어 어느 한쪽에서 재할당을 통해 값을 변경하더라도 간섭할 수 없음 196 | 197 | ## 11.2 객체 198 | 객체는 동적으로 프로퍼티가 추가되고 삭제될 수 있기때문에 메모리의 크기를 미리 정할 수 없음. 199 | 200 | > #### 자바스크립트 객체의 관리 방식 201 | > 프로퍼티 키를 인덱스로 사용하는 해시테이블 방식 (100%는 아니고 비슷) 202 | > 이는 객체를 생성하기 전 미리 프로퍼티와 메서드가 정해져 있어 메모리가 픽스되는 클래스 기반 프로그래밍 언어와 다르게 비효율적인 방식 203 | > 따라서 v8 엔진에서는 프로퍼티에 효율적으로 접근하기 위해 **[히든 클래스](https://engineering.linecorp.com/ko/blog/v8-hidden-class/)** 방식 선택 204 | 205 | ### 11.2.1 변경 가능한 값 206 | 객체를 할당한 변수가 기억하는 메모리 주소를 통해 메모리 공간에 접근 - 참조값에 접근 207 | 참조값 = 객체가 저장된 메모리 공간의 주소 208 | 209 | 객체를 할당한 변수 210 | - 재할당 없이 프로퍼티를 동적으로 추가 가능 211 | - 프로퍼티 값 갱신 가능 212 | - 프로퍼티 삭제 가능 213 | 214 | **여러 개의 식별자가 하나의 객체를 공유할 수 있다**는 단점 존재 215 | 216 | ### 11.2.2 참조에 의한 전달 217 | 객체를 가리키는 변수를 다른 변수에 할당하면 **원본의 참조값이 복사되어 전달** 218 | 219 | 두 개의 객체가 하나의 객체를 공유하기 때문에 한 쪽을 수정하면 다른 한 쪽에도 영향 220 | 221 | > #### 값에 의한 전달과 참조에 의한 전달 222 | > 두 방식 모두 식별자가 기억하는 메모리 공간에 대한 주소값을 가지고 있고 그 주솟값이 참조하는 값이 원시값이냐 참조값이냐의 차이만 존재 -------------------------------------------------------------------------------- /04) 10. 객체 리터럴 & 11. 원시값과 객체의 비교/June.md: -------------------------------------------------------------------------------- 1 | # 10. 객체 리터럴 2 | 3 | ## 10.1 객체란? 4 | 5 | - 자바스크립트는 객체 기반의 프로그래밍 언어다. 6 | - 원시 값(숫자, 문자열, boolean, etc...)와 같은 값을 제외하고는 전부 객체다. 7 | - 원시 타입은 하나의 값만 나타내지만 객체는 다양한 타입의 값을 하나의 단위로 구성한 복합적인 자료구조다. 8 | - 프로퍼티는 키와 값으로 구성된다. 9 | - 객체는 프로퍼티와 메서드로 구성된 집합체다. 10 | 11 | ```javascript 12 | var counter: { 13 | num: 0, // 프로퍼티 14 | increase: function () { // 메서드 15 | this.num++; 16 | } 17 | } 18 | ``` 19 | 20 | ## 10.2 객체 리터럴에 의한 객체 생성 21 | 22 | > 자바스크립트는 프로토타입 기반 객체지향 언어로서 클래스 기반 객체지향 언어와는 달리 다양한 객체 생성 방법을 지원한다. 23 | 24 | - 객체 리터럴 25 | - Object 생성자 함수 26 | - 생성자 함수 27 | - Object.create 메서드 28 | - 클래스 (es6) 29 | 30 | ## 10.3 프로퍼티 31 | 32 | > 객체는 프로퍼티의 집합이며, 프로퍼티는 키와 값으로 구성된다. 33 | 34 | ```javascript 35 | var person = { 36 | name: "hyeonsu", // key: name, value: 'hyeonsu' 37 | age: 20, // key: age, value: 20 38 | }; 39 | ``` 40 | 41 | - 프로퍼티를 나열할 때는 쉼표(,)로 구분 42 | - 프로퍼티 key로 사용할 수 있는 값은 문자열을 포함하는 모든 문자열 또는 심벌 값이다. 43 | - 프로퍼티 value로 사용할 수 있는 값은 자바스크립트에서 사용할 수 있는 모든 값이다. 44 | 45 | ```javascript 46 | // 예제 10-06 프로퍼티 키를 동적으로 생성하기 47 | var obj = {}; 48 | var key = "hello"; 49 | 50 | obj[key] = "world"; 51 | 52 | console.log(obj); // {hello: "world"} 53 | ``` 54 | 55 | ## 10.4 메서드 56 | 57 | > 프로퍼티가 함수일 경우 일반 함수와 구분하기 위해 메서드라고 부른다. 58 | 59 | ```javascript 60 | var circle = { 61 | sayHello: function () { 62 | // 메서드 63 | console.log("hello"); 64 | }, 65 | }; 66 | ``` 67 | 68 | ## 10.5 프로퍼티 접근 69 | 70 | > 프로퍼티에 접근하는 방법은 마침표 표기법(.)과 대괄호 프로퍼티 접근 연산자([...])를 사용하는 대괄호 표기법이 있다. 71 | 72 | - 식별자 네이밍 규칙을 준수하는 이름이면 둘 다 가능하다. 73 | - 객체에 존재하지 않는 프로퍼티에 접근하면 undefined를 반환한다. 이 때 참조 에러가 발생하지 않는다. (주의) 74 | 75 | ```javascript 76 | var person = { 77 | 'last-number': 'Lee', 78 | 1: 10, 79 | }; 80 | 81 | person.'last-name'; // 신택스 에러: Unexpected string 82 | person.last-name; // 브라우저: NaN 83 | // Node.js: 참조 에러: name is not defined 84 | person[last-name]; // last is not defined 85 | person['last-name']; // 'Lee' 86 | 87 | // 프로퍼티 키가 숫자로 이뤄진 문자열인 경우 따옴표를 생략할 수 있다. 88 | person.1; // 신택스 에러: Unexpected number 89 | person.'1'; // 신택스 에러: Unexpected string 90 | person[1]; // 10 91 | person['1'] // 10 92 | ``` 93 | 94 | - 식별자 네이밍 규칙을 준수하지 않을 땐 대괄호 프로퍼티로 접근해야 한다. 95 | 96 | ## 10.6 프로퍼티 갱신 97 | 98 | > 이미 존재하는 프로퍼티에 값을 할당하면 프로퍼티 값이 갱신된다. 99 | 100 | ## 10.7 프로퍼티 동적 생성 101 | 102 | > 존재하지 않는 프로퍼티에 값을 할당하면 프로퍼티가 동적으로 생성되어 추가되고 프로퍼티 값이 할당된다. 103 | 104 | ## 10.8 프로퍼티 삭제 105 | 106 | > delete 연산자를 통해 객체의 프로퍼티를 삭제할 수 있다. 107 | 108 | - 존재하지 않는 프로퍼티를 삭제 시도하면 아무런 에러 없이 그냥 넘어간다. 109 | 110 | ## 10.9 ES6에서 추가된 객체 리터럴의 확장 기능 111 | 112 | ### 10.9.1 프로퍼티 축약 표현 113 | 114 | ```javascript 115 | let x = 1, 116 | y = 2; 117 | 118 | const obj = { x, y }; 119 | 120 | console.log(obj); // {x: 1, y: 2}; 121 | ``` 122 | 123 | ### 10.9.2 계산된 프로퍼티 이름 124 | 125 | ```javascript 126 | var prefix = "prop"; 127 | var i = 0; 128 | 129 | obj[prefix + "-" + ++i] = i; 130 | obj[prefix + "-" + ++i] = i; 131 | obj[prefix + "-" + ++i] = i; 132 | 133 | console.log(obj); // {prop-1: 1, prop-2: 2, prop-3: 3} 134 | ``` 135 | 136 | ### 10.9.3 메서드 축약 표현 137 | 138 | ```javascript 139 | const objES5 = { 140 | name: "hyeonsu", 141 | sayHi: function () { 142 | console.log("hi"); 143 | }, 144 | }; 145 | 146 | const objES6 = { 147 | name: "hyeonsu", 148 | sayHi() { 149 | console.log("hi"); 150 | }, 151 | }; 152 | ``` 153 | 154 | - 메서드 축약 표현으로 정의한 메서드는 프로퍼티에 할당한 함수와 다르게 동작한다. 155 | - 이 부분은 메서드에서 자세히 살펴보세요. 156 | 157 | # 11. 원시 값과 객체의 비교 158 | 159 | 원시 타입과 객체 타입으로 구분하는 이유는 뭘까? 160 | 161 | - 원시 타입의 값, 즉 원시 값은 변경 불가능한 값이다. 이헤 비해 객체 타입의 값, 즉 객체는 변경 가능한 값이다. 162 | - 원시 값을 변수에 할당하면 변수에는 실제 값이 저장된다. 이에 비해 객체를 변수에 할당하면 변수에는 참조 값이 저장된다. 163 | - 원시 값을 갖는 변수를 다른 변수에 할당하면 원본의 원시 값이 복사되어 전달된다. 이를 값에 의한 전달이라 한다. 이에 비해 객체를 가리키는 변수를 다른 변수에 할당하면 원본의 참조 값이 복사되어 전달된다. 이를 참조에 의한 전달이라 한다. 164 | 165 | ## 11.1 원시 값 166 | 167 | ### 11.1.1 변경 불가능한 값 168 | 169 | - 원시 값은 변경 불가능한 값이다. 170 | - 한번 생성되면 읽기 전용 값으로서 변경할 수 없다. 171 | 172 | > 변경 불가능한 것은 변수가 아니라 값에 대한 진술이다. 173 | 174 | ### 11.1.3 값에 의한 전달 175 | 176 | > 변수에 변수를 할당했을 때 무엇이 어떻게 전달되는가? 177 | 178 | - 결론은 메모리 공간을 따로 만들어서 할당하기 때문에 추후에 변경했을 때 아무런 영향이 없다. 179 | - 결국은 두 변수의 원시 값은 서로 다른 메모리 공간에 저장된 별개의 값이 되어 어느 한쪽에서 재할당을 통해 값을 변경하더라도 서로 간섭할 수 없다는 것이다. 180 | 181 | ## 11.2 객체 182 | 183 | - 원시 값은 변경 불가능한 값이므로 원시 값을 갖는 변수의 값을 변경하려면 재할당 외에는 방법이 없다. 하지만 객체는 변경가능한 값이다. 184 | - 따라서 객체를 할당한 변수는 재할당 없이 객체를 직접 변경할 수 있다. 즉, 재할당 없이 프로퍼티를 동적으로 추가할 수 있고, 갱신, 삭제할 수도 있다. 185 | 186 | > 얕은 복사 vs 깊은 복사 187 | 188 | - 얕은 복사는 한 단계까지만 복사하는 것을 말한다. 189 | - 깊은 복사는 객체에 중첩되어 있는 객체까지 모두 복사하는 것을 말한다. 190 | -------------------------------------------------------------------------------- /04) 10. 객체 리터럴 & 11. 원시값과 객체의 비교/README.md: -------------------------------------------------------------------------------- 1 | # 10. 객체 리터럴 & 11. 원시값과 객체의 비교 2 | 3 | ## 정리 4 | 5 | - [춘식]() 6 | - [뽀송]() 7 | - [세인트](./saint.md) 8 | - [이안 - 메인 발표자]() 9 | - [준]() 10 | - [다나]() 11 | -------------------------------------------------------------------------------- /04) 10. 객체 리터럴 & 11. 원시값과 객체의 비교/choonsik.md: -------------------------------------------------------------------------------- 1 | # 10장 객체 리터럴 & 11장 원시값과 객체의 비교 2 | 3 | ## 10장 객체 리터럴 4 | 5 | ### 10.1 객체란? 6 | 7 | > 자바스크립트는 객체 기반의 프로그래밍 언어이며, 자바스크립트를 구성하는 거의 모든 것이 객체다. 8 | 9 | **원시 타입은 변경 불가능하지만 객체는 변경 가능한 값이다.** 10 | 11 | 객체는 0개 이상의 프로퍼티로 구성된 집합이며, 프로퍼티는 키와 값으로 구성된다. 12 | 자바스크립트에서 사용할 수 있는 모든 값은 프로퍼티 값이 될 수 있다. 13 | 14 | 자바스크립트의 함수는 일급 객체이므로 값으로 취급할 수 있으므로 함수도 프로퍼티 값(메서드)으로 사용할 수 있다. 15 | 16 | > 프로퍼티 : 객체의 상태를 나타내는 값 17 | > 메서드: 프로퍼티를 참조하고 조작할 수 있는 동작 18 | 19 | ### 10.2 객체 리터럴에 의한 객체 생성 20 | 21 | 자바스크립트는 프로토타입 기반 객체지향 언어로, 다양한 객체 생성 방법을 지원한다. 22 | 23 | - 객체 리터럴 24 | - 중괄호 내에 0개 이상의 프로퍼티 정의 (코드 블록이 아니므로 세미콜론이 붙는다!) 25 | - Object 생성자 함수 26 | - 생성자 함수 27 | - Object.create 메서드 28 | - 클래스 (ES6) 29 | 30 | ### 10.3 프로퍼티 31 | 32 | > 객체는 프로퍼티의 집합이며, 프로퍼티는 키와 값으로 구성된다. 33 | > 프로퍼티 키 : 빈 문자열을 포함하는 모든 문자열 또는 심벌 값 34 | > 프로퍼티 값 : 자바스크립트에서 사용할 수 있는 모든 값 35 | 36 | 가급적이면 식별자 네이밍 규칙을 준수하는 프로퍼티 키를 사용할 것을 권장한다. 37 | 식별자 네이밍 규칙을 준수하지 않을 경우 따옴표를 생략할 수 없다. 38 | 39 | 프로퍼티 키를 동적으로 생성하는 방법 40 | 41 | ```js 42 | var obj = {}; 43 | var key = "hello"; 44 | obj[key] = "world"; 45 | ``` 46 | 47 | ### 10.4 메서드 48 | 49 | 프로퍼티 값이 함수일 경우 일반 함수와 구분하기 위해 메서드라고 부른다. 50 | 51 | ### 10.5 프로퍼티 접근 52 | 53 | 접근방법 54 | 55 | 1. 마침표 표기법 56 | 2. 대괄호 표기법(대괄호 내 프로퍼티 키는 숫자가 아니라면 반드시 따옴표로 감싼 문자열이어야 한다.) 57 | 58 | 네이밍 규칙을 준수하면 1, 2 모두 사용할 수 있다. 59 | 준수하지 않으면 2만 사용할 수 있다. 60 | 61 | ### 10.6 프로퍼티 값 갱신 62 | 63 | 이미 존재하는 프로퍼티에 값을 할당하면 프로퍼티 값이 갱신된다. 64 | 65 | ### 10.7 프로퍼티 동적 생성 66 | 67 | 존재하지 않는 프로퍼티에 값을 할당하면 프로퍼티가 동적으로 생성되어 추가되고 프로퍼티 값이 할당된다. 68 | 69 | ### 10.8 프로퍼티 삭제 70 | 71 | delete 연산자는 객체의 프로퍼티를 삭제한다. 이때 피연산자는 프로퍼티 값에 접근할 수 있는 표현식이어야 한다. 72 | 73 | ### 10.9 ES6에서 추가된 객체 리터럴의 확장 기능 74 | 75 | #### 프로퍼티 축약 표현 76 | 77 | ```js 78 | var x = 1, 79 | y = 2; 80 | // 1 81 | var obj = { 82 | x: x, 83 | y: y, 84 | }; 85 | // 2 86 | var obj = { x, y }; 87 | ``` 88 | 89 | #### 계산된 프로퍼티 이름 90 | 91 | 문자열 또는 문자열로 타입 변환할 수 있는 값으로 평가되는 표현식을 사용해 프로퍼티 키를 객체 리터럴 내부/외부에서 동적으로 생성할 수 있다. 92 | 93 | #### 메서드 축약 표현 94 | 95 | 메서드를 정의하려면 프로퍼티 값으로 함수를 할당한다. 96 | 97 | ```js 98 | // ES5 99 | var obj = { 100 | name: "Lee", 101 | sayHi: function () { 102 | console.log("Hi!" + this.name); 103 | }, 104 | }; 105 | 106 | // ES6 107 | const obj = { 108 | name: "Lee", 109 | sayHi() { 110 | console.log("Hi!" + this.name); 111 | }, 112 | }; 113 | ``` 114 | 115 | // 메서드 축약 표현으로 정의한 메서드는 프로퍼티에 할당한 함수와 다르게 동작한다. 116 | 117 | ## 11장 원시값과 객체의 비교 118 | 119 | > 왜 구분할까? 120 | > 원시 값을 변수에 할당하면 변수에는 실제 값이 저장된다. 121 | > 객체를 변수에 할당하면 변수에는 참조 값이 저장된다. 122 | > 123 | > 원시 값을 갖는 변수를 다른 변수에 할당하면 원시 값이 복사되어 전달(pass by value)되고 124 | > 객체를 가리키는 변수를 다른 변수에 할당하면 원본의 참조 값이 복사되어 전달(pass by reference)된다. 125 | 126 | ### 11.1 원시 값 127 | 128 | #### 변경 불가능한 값(읽기 전용) 129 | 130 | 데이터의 신뢰성을 보장한다. 131 | 132 | #### 문자열과 불변성 133 | 134 | 자바스크립트는 개발자의 편의를 위해 원시 타입인 문자열 타입을 제공한다. 135 | 136 | 문자열은 유사 배열 객체이면서 이터러블이므로 배열과 유사하게 각 문자에 접근할 수 있다. 137 | 138 | > 유사 배열 객체 139 | > 배열처럼 인덱스로 프로퍼티 값에 접근할 수 있고 length 프로퍼티를 갖는 객체 140 | 141 | ```js 142 | var str = "string"; 143 | str[0] = "S"; // 이런 식으로 변경할 수 없다. 144 | str = "String"; // 이런 식으로 재할당해야 가능하다. 145 | ``` 146 | 147 | #### 값에 의한 전달 148 | 149 | ```js 150 | var score = 80; 151 | var copy = score; 152 | 153 | score = 100; 154 | console.log(score); // 100 155 | console.log(copy); // 80 156 | 157 | // 이 경우도 똑같다 158 | var copy = (score = 80); 159 | ``` 160 | 161 | score 변수와 copy 변수의 값은 다른 메모리 공간에 저장된 별개의 값이므로 서로 영향을 주지 않는다. 162 | 163 | > 값에 의한 전달이지만 사실은 메모리 주소가 전달되었다. 164 | > 다만 전달된 메모리 주소를 통해 메모리 공간에 접근해 값을 참조했다. 165 | 166 | ### 11.2 객체 167 | 168 | 객체는 프로퍼티의 개수가 정해져 있지 않으며, 동적으로 추가되고 삭제될 수 있다. 169 | 170 | > 자바스크립트 객체의 관리 방식 171 | > 자바스크립트 엔진은 해시 테이블과 유사하지만 더 나은 방법으로 객체를 구현한다. 172 | > 자바스크립트는 클래스 없이 객체를 생성할 수 있고, 동적으로 프로퍼티와 메서드를 추가할 수 있어 편리하지만 비용은 많이 드는 방식이다. 따라서 V8 자바스크립트 엔진에서는 프로퍼티 접근을 위해 동적 탐색 대신 히든 클래스(자바와 유사)를 사용해 C++ 정도의 성능을 보장한다. 173 | 174 | #### 변경 가능한 값 175 | 176 | 변수는 참조 값(메모리 공간의 주소 그 자체)을 통해 실제 객체에 접근할 수 있다. 177 | 178 | 객체를 할당한 변수는 재할당 없이 객체를 직접 변경(프로퍼티 추가, 갱신, 삭제)할 수 있다. 179 | 180 | > 얕은 복사와 깊은 복사 181 | > 얕은 복사 : 프로퍼티 한 단계까지 복사 (스프레드 문법) 182 | > 깊은 복사 : 객체에 중첩되어 있는 객체까지 모두 복사 (cloneDeep) 183 | > 들 다 원본과는 다른 객체이다. 184 | 185 | #### 참조에 의한 전달 186 | 187 | 객체를 가리키는 변수를 다른 변수에 할당하면 원본의 참조 값이 복사되어 전달되고, 이를 참조에 의한 전달이라고 한다. 188 | 189 | 여러 개의 식별자가 이처럼 하나의 객체를 공유하면, 서로 변경된 것에 영향을 받는다. 190 | 191 | > 변수에 저장된 값이 원시 값이나 참조 값이냐에 대한 차이만 있다. 192 | > 자바스크립트에는 값에 의한 전달만이 존재한다고 할 수 있다. 193 | -------------------------------------------------------------------------------- /05) 12. 함수/Ayaan.md: -------------------------------------------------------------------------------- 1 | # 12장 함수 2 | 3 | ## 12.1 함수란? 4 | 5 | ```js 6 | function add(x, y) { 7 | return x + y; 8 | } 9 | ``` 10 | 11 | 함수는 자바스크립트에서 가장 중요한 핵심 개념이다. 나 또한 프론트엔드 개발을 하면서 특히, React로 개발을 하면서 함수를 잘 이해하는 것이 정말 중요하다고 생각한다. 그리고 최근 들어 유독 함수형 프로그래밍이라는 제목의 블로그 글들을 자주 접하게 된다. 주변에 코틀린으로 함수형 프로그래밍 공부를 하는 사람들도 늘고 있다. 함수에 대해 깊숙이 파고 들면 들수록 많은 도움이 될 것이라 생각된다. 12 | 13 | 그렇다면 함수란 무엇인가? 함수는 일련의 과정을 문(statement)으로 구현하고 코드 블록으로 감싸서 하나의 실행 단위로 정의한 것이다. 함수 내부로 전달받는 변수를 매개변수(인자), 입력을 인수, 출력을 반환값이라고 한다. 14 | 15 | ## 12.2 함수를 사용하는 이유 16 | 17 | 그렇다면 함수를 사용하는 이유는 뭘까? 18 | 19 | - 함수는 몇 번이든 호출할 수 있으므로 **코드의 재사용 측면에서 매우 유용** 20 | - 재사용성을 높이기 때문에 **유지보수 측면에서 편의성을 높힘** 21 | - 내부 코드를 이해하지 않고 **함수 이름으로도 함수의 역할을 파악해서 가독성을 향상시킬 수 있음** 22 | 23 | ## 12.4 함수 정의 24 | 25 | 우리는 변수를 선언한다고 표현한다. 하지만 함수는 정의한다라고 표현한다. ECMAScript 사양에서도 이와 같이 표현하고 있다. 26 | 27 | ## 12.4.1 함수 선언문 28 | 29 | 함수 선언문은 함수 리터럴과 형태가 동일하다. 단, 함수 리터럴은 함수 이름을 생략할 수 있으나 함수 선언문은 함수 이름을 생략할 수 없다. 30 | 31 | ```js 32 | // 함수 이름을 생략할 수 없다. 33 | function (x, y) { 34 | return x + y 35 | } 36 | ``` 37 | 38 | 자바스크립트 엔진은 함수 이름이 있는 함수 리터럴을 단독으로 사용하면 함수 선언문으로 해석하고, 함수 리터럴이 값으로 평가되어야 한다면 함수 표현식으로 해석한다. 함수 선언문과 함수 표현식 이 둘은 어떤 차이가 있을까? 바로 내부 동작에 차이가 있다. 39 | 40 | ```js 41 | function foo() { 42 | console.log("foo"); 43 | } 44 | 45 | foo(); // foo 46 | ``` 47 | 48 | ```js 49 | (function bar() { 50 | console.log("bar"); 51 | }); 52 | 53 | bar(); // ReferenceError: bar is not defined 54 | ``` 55 | 56 | 그룹 연산자() 내에 있는 리터럴(bar)은 함수 선언문으로 해석되지 않고 함수 리터럴 표현식으로 해석된다. 함수 선언문은 피연산자로 사용할 수 없다. 그리고 이름 있는 기명 함수 리터럴은 코드의 문맥에 따라 함수 선언문 또는 함수 리터럴 표현식으로 해석된다. 57 | 58 | 함수 선언문 리터럴을 사용하면 자바스크립트 엔진은 암묵적으로 함수 이름을 가지고 식별자를 만든다. 그리고 식별자에 함수 객체를 할당한다. 59 | 60 | ```js 61 | function add(x, y) { 62 | return x + y; 63 | } 64 | 65 | // 자바스크립트 엔진은 다음과 같이 평가한다. 66 | var add = function add(x, y) { 67 | return x + y; 68 | }; 69 | ``` 70 | 71 | 우리는 함수 `add()`를 호출하면 함수 이름인 add로 호출하는 것 처럼 보이지만 사실 함수 식별자 add로 호출하는 것이다. 함수 이름은 함수 외부에서는 사용할 수 없다. (재귀함수처럼 함수 이름은 함수 안에서 함수 이름으로 함수를 호출할 수 있다.) 결론은 자바스크립트 엔진은 함수 선언문을 함수 표현식으로 변환해 함수 객체를 생성한다고 생각할 수 있다. 결국 함수 선언문을 사용해도 함수 표현식인 셈이다.. 72 | 73 | ## 12.4.2 함수 표현식 74 | 75 | 함수 리터럴로 생성한 함수 객체를 변수에 할당한 것을 함수 표현식이라고 한다. 그래서 함수를 저장한 변수는 자유롭게 값을 사용할 수 있다. 76 | 77 | ## 12.4.3 함수 생성 시점과 함수 호이스팅 78 | 79 | ```js 80 | console.log(add(2, 7)); // 9 81 | console.log(sub(2, 7)); // undefined 82 | 83 | // 함수 호이스팅 84 | function add(x, y) { 85 | return x + y; 86 | } 87 | 88 | // 변수 호이스팅 89 | var sub = function (x, y) { 90 | return x + y; 91 | }; 92 | ``` 93 | 94 | 위 코드를 보면 함수 선언문과 함수 표현식은 호이스팅도 나뉜다. 이러한 이유는 함수 선언문으로 정의한 함수와 함수 표현식으로 정의한 함수의 생성 시점이 다르기 때문이다. 함수 선언문으로 함수를 정의하면 런타임 이전에 함수 객체가 먼저 생성된다. 함수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징을 함수 호이스팅이라 한다. 95 | 96 | 하지만 호이스팅에도 함수 호이스팅과 변수 호이스팅으로 나뉘며, 이 둘은 차이가 있기 때문에 주의해야 한다. var 키워드를 사용한 변수 선언문과 함수 선언문은 런타임 이전에 자바스크립트 엔진에 의해 먼저 실행되어 식별자를 생성한다는 점에서 동일하다. 하지만 **var 키워드로 선언된 변수는 undefined로 초기화하고, 함수 선언문을 통해 암묵적으로 생성된 식별자는 함수 객체로 초기화 된다.** 그래서 위의 코드에서 `sub()`는 함수 표현식을 사용해서 함수를 변수에 할당했기 때문에 변수 호이스팅이 되었고, undefined가 반환된 것이다. 97 | 98 | 자바스크립트 책에서 JSON을 창안한 더글라스 크라포드는 이러한 호이스팅 문제 때문에 함수 표현식을 사용할 것을 권장한다고 한다. 99 | 100 | ## 12.4.5 화살표 함수 101 | 102 | 화살표 함수는 function 키워드를 간략한 방법으로 함수를 정의한 것이라고 보면 된다. 103 | 104 | ```js 105 | const add = (x, y) => x + y; 106 | 107 | console.log(add(2, 7)); //9 108 | ``` 109 | 110 | 화살표함수는 표현 방법뿐만 아니라 내부 동작 또한 간략화되어 있다. 화살표 함수는 생성자 함수를 사용할 수 없으며, 기존 함수와 this 바인딩 방식이 다르고, prototype 프로퍼티가 없으며 arguments 객체를 생성하지 않는다. 책에 나와 있는 이 부분만 유의해서 사용하면 좋을 것 같다. 111 | 112 | ## 12.5.1 매개변수와 인수 113 | 114 | ```js 115 | // () 괄호안에 있는게 매개변수 116 | function add(x, y) { 117 | return x + y; 118 | } 119 | 120 | // () 괄호안에는 값을 전달하는 인수 121 | const result = add(1, 2); 122 | ``` 123 | 124 | 함수가 호출되면 매개변수(위에서는 x, y)가 암묵적으로 매개변수가 생성되고 일반 변수와 마찬가지로 undefined로 초기화된 이후에 인수에 따라 순서대로 할당된다. 그리고 매개변수는 함수 외부에서 참조할 수 없다. 125 | 즉, 매개변수의 스코프는 함수 내에서만 존재한다. 126 | 127 | 만약 매개변수보다 인수가 더 많으면 어떻게 될까? 128 | 129 | ```js 130 | function (x, y) { 131 | console.log(arguments) 132 | // Arguments(3) [2, 3, 4, calle: ...] 133 | return x + y 134 | } 135 | 136 | console.log(add(2,3,4)); // 5 137 | ``` 138 | 139 | 초과된 인수는 암묵적으로 arguments 객체의 프로퍼티로 보관된다. 140 | 141 | ## 12.5.3 매개변수의 최대 개수 142 | 143 | 함수의 매개변수는 순서에 의미가 있다. 왜냐하면 매개변수는 인수를 순서대로 할당한다. 그래서 만약 매개변수의 순서나 개수가 다르게 되면 함수의 호출 방법, 반환값 마저 달라질 수 있기 때문이다. 그리고 책에서 권장하는 한가지가 있다. 바로 매개변수의 개수이다. 책에서는 매개변수를 3개까지만 권장하고, 그 이상을 사용해야할 경우 객체로 인수를 전달하는 것이 유리하다고 말하고 있다. 144 | 145 | 하지만 이전에도 배웠듯이 객체는 참조에 의한 값을 전달한다. 그래서 객체로 전달할 경우 부수효과를 일으킬 수 있으므로 주의해야 한다. (순수함수가 아니라는 뜻) 146 | 147 | ## 12.7 다양한 함수의 형태 148 | 149 | ## 12.7.1 즉시 실행 함수 150 | 151 | 즉시 실행 함수(IIFE)는 단 한번만 호출되며 다시 호출할 수 없다. 그리고 일반 함수처럼 값을 반환할 수도 있다. 152 | 153 | ```js 154 | const res = (function () { 155 | const a = 1; 156 | const b = 2; 157 | 158 | return a + b; 159 | })(); 160 | 161 | console.log(res); // 3 162 | ``` 163 | 164 | 즉시 실행 함수 내에 코드를 모아 두면 혹시 있을 수도 있는 변수나 함수 이름의 충돌을 방지할 수 있다. 그리고 만약 React에서 사용한다면 useEffect hook안에서는 async/await 사용할 수 없는데, 이럴 경우 다음과 같이 사용할 수 있다. 165 | 166 | ```js 167 | useEffect(() => { 168 | (async () => { 169 | const data = await fetchData(); 170 | }()) 171 | }, []); 172 | ``` 173 | 174 | ## 12.7.4 콜백 함수 175 | 176 | 함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수를 콜백 함수라고 하며, 매개 변수를 통해 함수의 외부에서 콜백 함수를 전달받은 함수를 고차 함수라고 한다. 그리고 고차 함수는 매개변수를 통해 전달받은 콜백 함수의 호출 시점을 결정해서 호출한다. 즉, 콜백 함수는 고차 함수에 의해 호출되며 이때 고차 함수는 필요에 따라 콜백 함수에 인수를 전달할 수 있다. 177 | 178 | ```js 179 | // logOdds는 단 한번만 실행된다. 180 | const logOdds = function (i) { 181 | if (i % 2) console.log(i); 182 | }; 183 | 184 | // 고차 함수에 콜백 함수를 전달 185 | repeat(5, logOdds); // 1 3 186 | ``` 187 | 188 | 위의 코드에서 logOdds는 단 한번만 호출된다. 하지만 고차 함수에 전달하면 고차 함수(repeat)가 호출될 때마다 콜백 함수(logOdds)가 생성된다. 그리고 콜백 함수는 비동기 처리에도 정말 많이 쓰이고 있다. 189 | 190 | ## 12.7.5 순수 함수와 비순수 함수 191 | 192 | 부수 효과가 없는 함수를 순수라고 한다. 순수 함수는 동일한 인수가 전달되면 언제나 동일한 값을 반환하는 함수다. 그렇기 때문에 객체를 전달받는 순간 순수함수라고 할 수 없다. 객체는 참조에 의한 값을 전달하기 때문에 외부 상태를 직접 참조를 통해 변경할 수 있기 때문이다. 그럼에도 순수 함수는 정말 중요한 개념이다. 그 이유는 함수형 프로그래밍 개념때문이라고 생각한다. 193 | 194 | 함수형 프로그래밍은 순수 함수와 보조 함수의 조합을 통해 외부 상태를 변경하는 부수 효과를 최소화해서 불변성을 지향하는 프로그래밍 패러다임이다. 이러한 특성을 이용한게 Rxjs 라이브러리이다. 함수형 프로그래밍을 하기 위해 React + Rxjs로 개발하시는 분들도 있다. 함수형 프로그래밍은 공부할수록 복잡하고 사용하기가 매우 어렵다. Rxjs또한 러닝커브가 낮지 않으므로 많은 삽질을 할 것 같다. 그럼에도 꼭 접해보고 싶은 기술이다. 195 | -------------------------------------------------------------------------------- /05) 12. 함수/June.md: -------------------------------------------------------------------------------- 1 | [함수 읽고 정리](https://junghyeonsu-dev.vercel.app/posts/Function) 2 | -------------------------------------------------------------------------------- /05) 12. 함수/Pposong.md: -------------------------------------------------------------------------------- 1 | # 12. 함수 2 | 3 | ## 12장 함수 4 | 5 | ### 12.1 함수란? 6 | 7 | 프로그래밍 언어의 **함수**는 일련의 과정을 문(`statement`)로 구현하고 코드 블록으로 감싸서 하나의 실행 단위로 정의한 것이다. 8 | 9 | 함수 내부로 입력을 전달받는 변수를 매개변수(`parameter`), 입력을 인수(`argument`), 출력을 반환값(return value)이라 한다. 10 | 11 | 함수는 함수 정의(`function definition`)를 통해 생성한다. 12 | 13 | ```ts 14 | // 함수 정의 15 | function add(x: number, y: number): number { 16 | return x + y; 17 | } 18 | ``` 19 | 20 | 함수를 호출하면 코드 블록에 담긴 문들이 일괄적으로 실행되고, 실행 결과, 즉 반환값을 반환한다. 21 | 22 | ```ts 23 | // 함수 호출 24 | const result = add(2, 5); 25 | 26 | console.log(result); 27 | ``` 28 | 29 | ### 12.2 함수를 사용하는 이유 30 | 31 | - 유지보수 비용의 감소 32 | - 코드의 신뢰성 제고 33 | - 코드의 가독성 향상 34 | 35 | 함수를 사용함으로써 코드의 중복을 억제하고 재사용성을 높인다. 36 | 37 | 따라서 유지보수의 편의성을 높이고 실수를 줄여 코드의 신뢰성을 높인다. 38 | 39 | 또한 함수도 객체이기 때문에 이름을 가진다. 40 | 41 | 적절한 함수 이름은 코드의 가독성을 향상시킨다. 42 | 43 | ### 13.3 함수 리터럴 44 | 45 | ```ts 46 | // 변수에 함수 리터럴을 할당 47 | const f = function add(x: number, y: number): number { 48 | return x + y; 49 | } 50 | ``` 51 | 52 | 함수는 객체지만 일반 객체와는 다르다. 53 | 54 | 일반 객체는 호출할 수 없지만 함수는 호출할 수 있다. 55 | 56 | 그리고 일반 객체에는 없는 함수 객체만의 고유한 프로퍼티를 갖는다. 57 | 58 | ### 12.4 함수 정의 59 | 60 | 함수를 정의하는 방법에는 4가지가 있다. 61 | 62 | #### 12.4.1 함수 선언문 63 | 64 | ```ts 65 | function add(x: number, y: number): number { 66 | return x + y; 67 | } 68 | ``` 69 | 70 | 함수 선언문은 표현식이 아닌 문이다. 71 | 따라서 완료 값 undefined가 출력된다. 72 | 73 | 그리고 함수 선언문은 함수 이름을 생략할 수 없다. 74 | 75 | > 자바스크립트 엔진은 생성된 함수를 호출하기 위해 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성하고, 거기에 함수 객체를 할당한다. 76 | 77 | #### 12.4.2 함수 표현식 78 | 79 | ```ts 80 | const add = function(x: number, y: number): number { 81 | return x + y; 82 | } 83 | ``` 84 | 85 | 함수는 일급 객체이므로 함수 리터럴로 생성한 함수 객체를 변수에 할당할 수 있다. 86 | 87 | 함수 리터럴의 함수 이름은 생략할 수 있다. 88 | 89 | #### 12.4.3 함수 생성 시점과 함수 호이스팅 90 | 91 | 함수 표현식으로 정의한 함수는 함수 표현식 이전에 호출할 수 없다. 그러나 함수 선언문으로 정의한 함수는 함수 선언문 이전에 호출할 수 있다. 92 | 93 | 함수 표현식으로 함수를 정의하면 함수 호이스팅이 발생하는 것이 아니라 변수 호이스팅이 발생하기 때문이다. 94 | 95 | #### 12.4.3 Function 생성자 함수 96 | 97 | ```ts 98 | const add = new Function('x', 'y', 'return x + y'); 99 | ``` 100 | 101 | 이 방법은 일반적이지 않으며 바람직하지도 않다. 102 | 103 | Function 생성자로 생성한 함수는 클로저를 생성하지 않는 등 다른 방법으로 생성한 함수와 다르게 동작한다. 104 | 105 | #### 12.4.4 화살표 함수(ES6) 106 | 107 | ```ts 108 | const add = (x: number, y: number): number => x + y; 109 | ``` 110 | 111 | 화살표 함수는 생성자 함수로 사용할 수 없으며, 기존 함수와 this 바인딩 방식이 다르고 prototype 프로퍼티가 없으며 arguments 객체를 생성하지 않는다. 112 | 113 | ### 12.5 함수 호출 114 | 115 | #### 12.5.1 매개변수와 인수 116 | 117 | 매개변수는 함수를 정의할 때 선언하며, 함수 몸체 내부에서 변수와 동일하게 취급된다. 118 | 119 | 함수가 호출될 때마다 매개변수는 이와 같은 단계를 거친다. 120 | 121 | 1. 함수 호출을 통해 인수 전달 122 | 2. 매개변수가 undefined로 초기화됨 123 | 3. 인수가 순서대로 매개변수에 할당됨 124 | 125 | 매개변수보다 인수가 더 많은 경우 초과된 인수는 무시된다. 126 | 127 | 그러나 버려지는 것이 아니라 arguments 객체의 프로퍼티로 보관된다. 128 | 129 | #### 12.5.2 인수 확인 130 | 131 | 함수 내부에서 적절한 인수가 전달되었는지 확인하더라도 부적절한 호출을 사전에 방지할 수는 없고, 에러는 런타임에 발생하게 된다. 132 | 133 | ES6에 도입된 매개변수 기본값을 사용하면 함수 내에서 수행하던 인수 체크 및 초기화를 간소화할 수 있다. 134 | 135 | ```ts 136 | function add(a: number = 0, b: number = 0, c: number = 0): number { 137 | return a + b + c; 138 | } 139 | 140 | console.log(add(1, 2, 3)); // 6 141 | console.log(add(1, 2)); // 3 142 | console.log(add(1)); // 1 143 | console.log(add()); // 0 144 | ``` 145 | 146 | #### 12.5.3 매개변수의 최대 개수 147 | 148 | 이 부분은 클린 코드에서 설명한 것으로 대체한다. 149 | 150 | 매개변수의 개수를 `최대 3개!` 이렇게 제한하는 것은 교조주의에 빠지게 할 뿐이라는 것을 기억하자. 151 | 152 | [Clean Code 3. 함수](https://velog.io/@dnr6054/Clean-Code-3-%ED%95%A8%EC%88%98#%ED%95%A8%EC%88%98-%EC%9D%B8%EC%88%98) 153 | 154 | #### 12.5.4 반환문 155 | 156 | 반환문은 두 가지 역할을 한다. 157 | 158 | 첫째, 반환문은 함수의 실행을 중단하고 함수 몸체를 빠져나간다. 따라서 반환문 이후에 다른 문이 존재하면 그 문은 실행되지 않고 무시된다. 159 | 160 | 둘째, 반환문은 return 키워드 뒤에 오는 표현식을 평가해 반환한다. 명시적으로 지정하지 않으면 undefined가 반환된다. 161 | 162 | ### 12.6 참조에 의한 전달과 외부 상태의 변경 163 | 164 | 원시값은 값에 의한 전달, 객체는 참조에 의한 전달 방식으로 동작한다. 165 | 166 | 매개변수도 변수와 동일하게 취급되므로 위 방식을 그대로 따른다. 167 | 168 | 이러한 문제의 해결방법 중 하나는 객체를 불변 객체로 만들어 사용하는 것이다. 169 | 170 | 이를 통해 객체의 상태 변경을 원천봉쇄하고, 상태 변경이 필요한 경우에는 객체의 방어적 복사를 통해 원본 객체를 완전히 복제, 즉 깊은 복사를 통해 새로운 객체를 생성하고 재할당을 통해 교체한다. 171 | 172 | ### 12.7 다양한 함수의 형태 173 | 174 | #### 12.7.1 즉시 실행 함수 175 | 176 | 즉시 실행 함수는 단 한번만 호출되며 다시 호출할 수 없다. 177 | 178 | ```ts 179 | (function() { 180 | var a = 3; 181 | var b = 5; 182 | return a * b; 183 | })(); 184 | ``` 185 | 186 | 즉시 실행 함수는 익명 함수를 사용하는 것이 일반적이다. 187 | 188 | 이름을 쓴다고 해도 외부에서 호출할 수는 없다. 189 | 190 | 그리고 무조건 소괄호로 묶어줘야 한다. 191 | 192 | #### 12.7.2 재귀 함수 193 | 194 | 재귀함수는 Stack Overflow 에러를 발생시킬 수 있으므로 반복문을 사용하는 것보다 재귀함수를 사용하는 편이 더 이해하기 쉬울 때에만 한정적으로 사용하는 것이 바람직하다. 195 | 196 | #### 12.7.3 중첩 함수 197 | 198 | ES6부터 함수 정의는 문이 위치할 수 있는 문맥이라면 어디든지 가능하다. 199 | 200 | 그러나 호이스팅으로 인해 혼란이 생길 수 있으므로 if문이나 for문 등의 코드 블록에서 함수 선언문을 통해 함수를 정의하는 것은 바람직하지 않다. 201 | 202 | #### 12.7.4 콜백 함수 203 | 204 | 함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수를 콜백 함수라고 하며, 매개변수를 통해 함수의 외부에서 콜백 함수를 전달받은 함수를 고차함수라고 한다. 205 | 206 | #### 12.7.5 순수 함수와 비순수 함수 207 | 208 | 어떤 외부 상태에 의존하지도 않고 변경하지도 않는, 즉 부수 효과가 없는 함수를 순수 함수라 하고, 외부 상태에 의존하거나 외부 상태를 변경하는, 즉 부수 효과가 있는 함수를 비순수 함수라고 한다. 209 | -------------------------------------------------------------------------------- /05) 12. 함수/README.md: -------------------------------------------------------------------------------- 1 | # 12. 함수 2 | 3 | ## 정리 4 | 5 | - [춘식]() 6 | - [뽀송]() 7 | - [세인트]() 8 | - [이안]() 9 | - [준 - 메인 발표자]() 10 | - [다나]() 11 | -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/Ayaan.md: -------------------------------------------------------------------------------- 1 | ## 23장 실행 컨텍스트 2 | 3 | ## 23.1 소스코드의 타입 4 | 5 | - 전역 코드(global code): 전역에 존재하는 소스코드이며, 전역에 정의된 함수, 클래스는 포함 X 6 | - 함수 코드(function code): 함수 내부에 존재하는 소스코드이며, 함수 내부에 중첩된 함수, 클래스는 포함 X 7 | - eval 코드: 빌트인 전역 함수인 eval 함수에 인수로 전달되어 실행되는 소스코드 8 | - 모듈 코드: 모듈 내부에 존재하는 소스코드이며, 모듈 내부의 함수, 클래스 포함 X 9 | 10 | 전역 코드 11 | 12 | - 전역 변수를 관리하기 위해 존재 13 | - var키워드로 선언된 전역 변수와 함수 선언문으로 정의된 전역 함수를 전역 객체의 프로퍼티와 메서드로 바인딩하기 위해 전역 객체로 연결 14 | 15 | 함수 코드 16 | 17 | - 지역 스코프를 생성하고 지역 변수, 매개변수, arguements 객체를 관리 18 | - 생성한 지역 스코프를 전역 스코프에서 시작하는 스코프 체인의 일원으로 연결 19 | 20 | ## 23.2 소스코드의 평가와 실행 21 | 22 | 모든 소스코드는 실행에 앞서 평가 과정을 거치며 코드를 실행하기 위한 준비를 한다. 즉, 자바스크립트 엔진은 소스코드의 평가와 소스코드의 실행 2가지 과정으로 나누어 처리한다. 23 | 24 | 1. 소스코드의 평가 과정을 거침 25 | 26 | - 실행 컨텍스트를 생성 27 | - 변수, 함수 등의 선언문만 먼저 실행 후 실행 컨텍스트가 관리하는 스코프에 등록 28 | 29 | 2. 선언문을 제외한 소스코드가 순차적으로 실행 (런타임) 30 | 3. 변수나 함수의 참조를 실행 컨텍스트가 관리하는 스코프에서 검색해서 취득 31 | 4. 소스 코드의 실행 결과를 스코프에 다시 등록 32 | 33 | ## 23.3 실행 컨텍스트의 역할 34 | 35 | 코드가 실행되려면 다음과 같이 스코프, 식별자, 코드 실행 순서 등의 관리가 필요하다. 선언에 의해 생성된 모든 식별자(변수, 함수, 클래스 등)를 스코프를 구분하여 등록하고 관리해야 한다. 그리고 스코프는 중첩 관계에 의해 스코프 체인을 형성해야 한다. 이유는 상위 스코프로 이동하여 식별자를 검색할 수 있어야 하기 때문이다. 또 현재 실행 중인 코드의 실행 순서를 변경할 수 있어야 하며 다시 돌아갈 수도 있어야 한다. 36 | 37 | 실행 컨텍스트는 소스코드를 실행하는 데 필요한 환경을 제공하고 코드의 실행 결과를 실제로 관리하는 영역이다. 실행 컨텍스트는 식별자(변수, 함수, 클래스 등의 이름)를 등록하고 관리하는 스코프와 코드 실행 순서 관리를 구현한 내부 메커니즘으로, 모든 코드는 실행 컨텍스트를 통해 실행하고 관리된다. 38 | 39 | - 식별자와 스코프 => 렉시컬 환경으로 관리 40 | - 코드 실행 순서 => 실행 컨텍스트 스택으로 관리 41 | 42 | ## 23.4 실행 컨텍스트 스택 43 | 44 | 실행 컨텍스트 스택은 코드의 실행 순서를 관리한다. 실행 컨텍스트 스택의 최상위에 존재하는 실행 컨텍스트는 언제나 현재 실행 중인 코드의 실행 컨텍스트다. 45 | 46 | ## 23.5 렉시컬 환경 47 | 48 | 렉시컬 환경은 식별자와 식별자에 바인딩된 값, 그리고 상위 스코프에 대한 참조를 기록하는 자료구조로 실행 컨텍스트를 구성하는 컴포넌트다. 실행 컨텍스트 스택이 실행 순서를 관리한다면 렉시컬 환경은 스코프와 식별자를 관리한다. 렉시컬 환경은 스코프를 구분하여 식별자를 등록하고 관리하는 저장소 역할을 하는 렉시컬 스코프의 실체다. 49 | 50 | ## 23.6 실행 컨텍스트의 생성과 식별자 검색 과정 51 | 52 | 1. 전역 실행 컨텍스트 생성 53 | 54 | 먼저 비어있는 전역 실행 컨텍스트를 생성하여 실행 컨텍스트 스택에 푸시한다. 55 | 56 | 2. 전역 렉시컬 환경 생성 57 | 58 | 전역 렉시컬 환경을 생성하고 전역 실행 컨텍스트에 바인딩한다. 전역 렉시컬 환경 생성안에서 this 바인딩은 전역 환경 레코드의 [[GblobalThisValue]] 내부 슬롯에 this가 바인딩한다. 일반적으로 전역 코드에서 this는 전역 객체를 가리키는데, 전역 환경 레코드의 [[GblobalThisValue]] 내부 슬롯에는 전역 객체가 바인딩된다. 그래서 전역 코드 this를 참조하면 전역 환경 레코드의 [[GblobalThisValue]] 내부 슬롯에 바인딩되어 있는 객체가 반환된다. 59 | 60 | ## 23 실행 컨텍스트와 블록 레벨 스코프 61 | 62 | ```js 63 | let x = 1; 64 | 65 | if (true) { 66 | let x = 10; 67 | console.log(x); // 10 68 | } 69 | 70 | console.log(x); // 1 71 | ``` 72 | 73 | if문의 코드 블록 내에서 let 키워드로 변수가 선언되었다. let 키워드는 기본적으로 블록 레벨 스코프를 가지므로, 블록 렉시컬 환경을 생성한다. 그리고 렉시컬 환경을 새롭게 생성하여 기존의 전역 렉시컬 환경을 교체한다. 이때 새롭게 생성된 if 문의 블록 렉시컬 환경은 if 문이 실행되기 전의 전역 렉시컬 환경을 가리킨다. 그리고 if문이 종료되면 그때 if문의 코드 블럭이 실행되기 이전의 환경(전역 렉시컬 환경)으로 되돌린다. 이와 같은 설명은 if문외에 모든 블록 레벨 스코프에 해당된다. 74 | 75 | ## 13장 스코프 76 | 77 | 스코프란 값이 변수에 할당되고, 그 변수가 유효한 범위를 스코프라고 한다. 책에서는 더 정확히 설명하고 있는데, 모든 식별자가 선언된 위치에 의해 다른 코드가 식별자 자신을 참조할 수 있는 유효 범위가 결정되는 것을 스코프라고 한다고 나와있다. 즉, 식별자가 유효한 범위를 말한다고 한다. 78 | 79 | 스코프는 실행 컨텍스트와도 연관이 있는데, 소스코드를 평가하기 위해 식별자를 검색하는데, 자바스크립트 엔진이 식별자를 검색할 때 바로 이 스코프의 규칙에 따라 검색을 한다는 것이다. 80 | 81 | 스코프 체인의 개념은 스코프가 함수의 중첩에 의해 계층적인 구조를 갖는 것을 뜻한다. 즉, 지역 스코프가 외부 함수와 계층적 구조를 가질 때 우리는 스코프 체인이라고 한다. 변수를 참조할 때 자바스크립트 엔진은 스코프 체인을 통해 변수를 참조하는 코드의 스코프에서 시작하여 상위 스코프 방향으로 이동하며 선언된 변수를 검색한다. 방금과 같은 개념의 스코프 체인은 다음 장에서 배울 클로저와도 깊은 연관이 있기 때문에 깊게 공부하는 것이 좋다. 그리고 또 알아야 할 점은 상위 스코프에서 유효한 변수는 하위 스코프에 자유롭게 참조가 가능하지만, 하위 스코프에서 유효한 변수를 상위 스코프에서 참조할 수 없다. 82 | 83 | 스코프에는 렉시컬 스코프의 개념도 있다. 함수를 어디서 호출했냐가 아니라 어디서 정의했는지에 따라 스코프를 결정하는 것을 뜻한다. 자바스크립트에서 함수가 호출된 위치는 상위 스코프에 아무런 영향을 주지 않는다. 즉 함수의 상위 스코프는 언제나 자신이 정의된 스코프라고 할 수 있다. 이 개념을 알아야 하는 이유는 함수가 호출될 때마다 상위 스코프를 참조할 필요가 있기 때문이다. 84 | -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/IMG_0996044C3E28-1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/IMG_0996044C3E28-1.jpeg -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/IMG_21F6C19D6637-1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/IMG_21F6C19D6637-1.jpeg -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/IMG_5B20F389C697-1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/IMG_5B20F389C697-1.jpeg -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/IMG_DEFDBAC3D287-1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/IMG_DEFDBAC3D287-1.jpeg -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 1.png -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 10.png -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 11.png -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 12.png -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 13.png -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 14.png -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 15.png -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 16.png -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 17.png -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 18.png -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 2.png -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 3.png -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 4.png -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 5.png -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 6.png -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 7.png -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 8.png -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled 9.png -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/Untitled.png -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/프로젝트_아이디어-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/06) 23. 실행컨텍스트 & 13. 스코프/DanaImgs/프로젝트_아이디어-4.jpg -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/June.md: -------------------------------------------------------------------------------- 1 | [실행 컨텍스트 읽고 정리](https://junghyeonsu-dev.vercel.app/posts/Execution-context) 2 | -------------------------------------------------------------------------------- /06) 23. 실행컨텍스트 & 13. 스코프/README.md: -------------------------------------------------------------------------------- 1 | # 23. 실행컨텍스트 & 13. 스코프 2 | 3 | ## 정리 4 | 5 | - [춘식]() 6 | - [뽀송]() 7 | - [세인트]() 8 | - [이안]() 9 | - [준]() 10 | - [다나 - 메인 발표자]() 11 | -------------------------------------------------------------------------------- /07) 14. 전역변수의 문제점 & 15. let, const와 블록 레벨 스코프/June.md: -------------------------------------------------------------------------------- 1 | # 14. 전역 변수의 문제점 2 | 3 | ```javascript 4 | function foo() { 5 | var x = "local"; 6 | console.log(x); // local 7 | return x; 8 | } 9 | 10 | foo(); 11 | console.log(x); // ReferenceError: x is not defined 12 | ``` 13 | 14 | foo 함수를 호출하면 함수 몸체의 다른 문들이 순차적으로 실행되기 이전에 `x` 변수의 선언문이 자바스크립트 엔진에 의해 가장 먼저 실행됩니다. 15 | 16 | 그럼 `x` 변수가 `undefined`로 초기화되고, 변수 할당문이 실행되면 x 변수에 값이 할당됩니다. 그리고 함수가 종료하면 `x` 변수도 소멸됩니다. 17 | 18 | 지역변수는 생명 주기는 함수의 생명 주기와 일치합니다. 19 | 20 | 함수 내부에서 선언된 지역 변수는 함수가 생성한 스코프에 등록됩니다. 스코프는 렉시컬 환경이라 부르는 물리적 실체가 있는데, 그래서 변수는 스코프가 소멸될 때까지 유효합니다. 21 | 22 | 근데 해당 메모리 공간을 계속 참조하고 있으면 함수가 종료되더라도, 스코프와 변수는 소멸하지 않고 생존하게 됩니다. 23 | 24 | 호이스팅은 스코프를 단위로 동작합니다. 25 | 26 | ## 14.1.2 전역 변수의 생명 주기 27 | 28 | 전역에서 생성한 변수들은 전역 객체의 생명주기와 동일해진다. 29 | 브라우저에서 전역 객체는 window다. 전역 객체 window는 브라우저를 닫기 전까지 유효한데, 그러면 `var`로 선언한 전역 변수는 브라우저를 닫을 때까지 유효하다. 30 | 31 | # 14.2 전역 변수의 문제점 32 | 33 | ## 1. 암묵적 결합 34 | 35 | > 모든 코드가 전역 변수를 참조하고, 재변경하겠다. 36 | 37 | 모든 코드가 참조하고 변경 가능 하면? 38 | 39 | - 가독성이 떨어질 수 있다. 40 | - 의도치 않은 변경이 일어날 수 있다. 41 | 42 | ## 2. 긴 생명주기 43 | 44 | > 전역 변수는 생명 주기가 길다. 45 | 46 | 생명 주기가 길면? 47 | 48 | - 메모리 소비 기간이 길어진다. 49 | - 의도치 않은 변경이 일어날 수 있다. 50 | - 상태를 변경할 수 있는 기회와 시간이 길어진다. 51 | 52 | ## 3. 스코프 체인 상에서 종점에 존재 53 | 54 | > 변수를 검색할 때 가장 마지막에 검색된다. 55 | 56 | 가장 마지막에 검색되면? 57 | 58 | - 검색의 속도가 가장 느리다. : 가장 마지막에 검색되니까 (속도의 차이는 크지 않지만 차이는 분명히 있다.) 59 | 60 | ## 4. 네임스페이스 오염 61 | 62 | > 자바스크립트는 파일이 분리되어 있어도 전역 스코프를 공유한다. 63 | 64 | 다른 파일 내에서 동일한 이름으로 명명된 전역 변수나 전역 함수가 같은 스코프 내에 존재할 경우 예상치 못한 결과를 가져올 수 있다. 65 | 66 | # 14.3 전역 변수의 사용을 억제하는 방법 67 | 68 | > 전역 변수는 남용하면 안된다. 변수의 스코프는 좁을수록 좋다. 69 | 70 | 1. 즉시실행함수 (IIFE) 71 | 72 | 모든 코드를 즉시 실행 함수로 감싸면 모든 변수는 즉시 실행 함수의 지역 변수가 된다. 73 | 74 | ```javascript 75 | (() => { 76 | // ... 77 | }()); 78 | ``` 79 | 80 | 2. 네임스페이스 객체 사용 81 | 82 | 네임스페이스 객체 자체가 또 전역 변수에 할당되니까 그닥 유용한 방법은 아닌 것 같다고 책에서 그랬다. 83 | 84 | ```javascript 85 | var MYAPP = {}; // 전역 네임스페이스 객체 86 | ``` 87 | 88 | 3. 모듈 패턴 89 | 90 | > 모듈 패턴은 자바스크립트의 강력한 기능인 클로저를 기반으로 동작한다. 91 | 92 | ```javascript 93 | var Counter = (function () { 94 | // private member 95 | var num = 0; 96 | 97 | // public member 98 | return { 99 | increase: () => { 100 | return ++num; 101 | }, 102 | decrease: () => { 103 | return --num; 104 | }, 105 | }; 106 | })(); 107 | ``` 108 | 109 | 외부에 노출하고 싶은 건 return 객체에 포함하지 않으면 되고, 외부에 노출하고 싶다면 return에 노출시키면 된다. 이렇게 캡슐화를 실현시킬 수 있다. 110 | 111 | 4. ES6 모듈 112 | 113 | > ES6 모듈을 사용하면 더는 전역 변수를 사용할 수 없다. ES6 모듈은 파일 자체의 독자적인 모듈 스코프를 제공한다. 114 | 115 | ```html 116 | 117 | ``` 118 | 119 | ES6 문법은 구형 브라우저에서는 동작하지 않으므로, 바벨을 통해서 문법을 전환하거나, 웹팩 같은 모듈 번들러를 통해서 합치는 것이 일반적이다. 120 | 121 | # 15. let, const 키워드와 블록 레벨 스코프 122 | 123 | ES5까지는 `var`로만 변수를 선언할 수 있었다. `var`의 특징은 다음과 같다. 124 | 125 | ## 15.1.1 변수 중복 선언 허용 126 | 127 | ```javascript 128 | var x = 1; 129 | 130 | // doing something 131 | 132 | // 중복 선언을 허용한다. 133 | var x = 100; 134 | ``` 135 | 136 | `var` 키워드 중복 선언을 해도 에러가 나지 않기 때문에 만약 동일한 이름의 변수가 선언되어 있는 것을 모르고 변수를 중복 선언하면서 덮어 씌울 수 있기 때문에 의도치 않은 동작이 일어날 수 있다. 137 | 138 | ## 15.1.2 함수 레벨 스코프 139 | 140 | `var` 키워드로 선언한 변수는 함수 레벨 스코프를 가진다. 141 | 그래서 블록 내에서 선언해도 모두 전역 변수가 된다. 142 | 143 | ```javascript 144 | var x = 1; 145 | 146 | // x는 전역 변수다. 147 | // 이미 선언된 값을 덮어 씌운다. 148 | if (true) { 149 | var x = 10; 150 | } 151 | 152 | console.log(x); // 10 153 | ``` 154 | 155 | ## 15.1.3 변수 호이스팅 156 | 157 | `var` 키워드는 선언 이전에 참조가 가능하다. 158 | 159 | `var`는 undefined로 맨 처음 선언이 되고, 실제 값은 할당문에서 일어나기 때문에 그 전에 참조를 하면 undefined가 뜬다. 160 | 161 | 에러를 발생하지 않지만 가독성이 떨어지고, 예측이 불가능하다. 162 | 163 | # 15.2 let 키워드 164 | 165 | ## 15.2.1 변수 중복 선언 금지 166 | 167 | `var` 키워드와 다르게 중복 선언하게 된다면 에러를 뱉는다. 168 | 169 | ## 15.2.2 블록 레벨 스코프 170 | 171 | `let` 키워드는 블록 레벨 스코프를 따른다. 함수, if문, for문, while문, try-catch문 등이 블록이고, 이 안의 생명주기와 같게 동작한다. 172 | 173 | ```javascript 174 | let i = 10; // 전역 변수 175 | 176 | function foo() { 177 | let i = 100; // 함수 레벨 스코프 178 | 179 | // 블록 레벨 스코프 180 | for (let i = 0; i < 3; i++) { 181 | console.log(i); // 0, 1, 2 182 | } 183 | 184 | console.log(i); // 100 185 | } 186 | 187 | foo(); 188 | console.log(i); // 10 189 | ``` 190 | 191 | ## 15.2.3 변수 호이스팅 192 | 193 | `let` 키워드 변수는 **선언 단계**와 **초기화 단계**가 분리되어 진행된다. 자바스크립트 엔진은 선언을 먼저 실행하고, 변수 선언문에 도달했을 때 초기화가 진행된다. 194 | 195 | 만약 초기화 이전에 변수에 접근하려고 하면 자바스크립트는 참조 에러를 뱉는다. 196 | 197 | `var`는 선언과 동시에 `undefined`를 할당해서 선언과 초기화 단계 사이에서 접근을 할 수 있었는데, `let` 키워드는 선언 이후에 초기화가 일어나지 않았을 때 접근을 하려고 하면 참조 에러를 일으킨다. 그래서 변수를 참조할 수 없는 이 구간을 일시적 사각지대(TDZ: Temporal Dead Zone)라고 부른다. 198 | 199 | `let`과 `const`가 호이스팅이 동작하지 않는 것 처럼 동작해서 호이스팅이 일어나지 않는다고 생각할 수 있지만, 실제로는 일어난다. 200 | 201 | ```javascript 202 | let foo = 1; // 전역 변수 203 | 204 | { 205 | // 참조 에러가 이유가 호이스팅이 일어났다는 이유다. 206 | // 원래는 호이스팅이 일어나지 않았으면 1을 띄워야 하는데 207 | // 호이스팅이 일어나서, 할당문을 아직 만나지 못했기 때문에 참조에러를 띄우는 것! 208 | console.log(foo); // ReferenceError 209 | let foo = 2; // 지역 변수 210 | } 211 | ``` 212 | 213 | # 15.3 const 키워드 214 | 215 | `let`과 `const`는 거의 비슷하게 동작한다. 그래서 `let`과 다른 점을 살펴보자 216 | 217 | ## 15.3.1 선언과 초기화 218 | 219 | `let` 키워드는 선언과 동시에 초기화를 해주지 않아도 에러가 나지 않는다. 220 | 하지만 `const` 키워드는 선언과 동시에 초기화를 해주지 않으면 에러가 난다. 221 | 222 | ```javascript 223 | const a; // SyntaxError: Missing initializer in const declaration 224 | ``` 225 | 226 | ## 15.3.2 재할당 금지 227 | 228 | ```javascript 229 | const foo = 1; 230 | foo = 2; // TypeError: Assignment to constant variable. 231 | ``` 232 | 233 | ## 15.3.4 const와 객체 234 | 235 | > const에 원시 값을 할당한 경우에는 변경이 불가능하지만, 객체를 할당한 경우에는 변경할 수 있다. 236 | 237 | ```javascript 238 | const me = { name: "hyeonsu" }; 239 | 240 | me.name = "sally"; 241 | 242 | console.log(me); // { name: 'sally' } 243 | ``` 244 | 245 | **재할당 금지**와 **불변성**은 다른 말이다. 객체는 참조값을 저장하고 있기 때문에 참조 값의 저장, 삭제, 추가는 가능하다. 246 | -------------------------------------------------------------------------------- /07) 14. 전역변수의 문제점 & 15. let, const와 블록 레벨 스코프/README.md: -------------------------------------------------------------------------------- 1 | # 14. 전역변수의 문제점 / 15. let, const와 블록 레벨 스코프 2 | 3 | ## 정리 4 | 5 | - [춘식 - 메인 발표자]() 6 | - [뽀송]() 7 | - [세인트](./saint.md) 8 | - [이안]() 9 | - [준]() 10 | - [다나]() 11 | -------------------------------------------------------------------------------- /07) 14. 전역변수의 문제점 & 15. let, const와 블록 레벨 스코프/dana.md: -------------------------------------------------------------------------------- 1 | # 14. 전역 변수의 문제점 2 | 3 | ## 14.1 변수의 생명 주기 4 | ### 14.1.1 지역 변수의 생명 주기 5 | 변수는 선언에 의해 생성되고, 할당을 통해 값을 값을 갖고 소멸하는 생명주기를 갖고 있음. 6 | 변수는 자신이 선언된 위치에서 생성되고 소멸 7 | -> **`전역변수`의 생명주기** == 애플리케이션의 생명 주기 8 | -> **`지역변수`의 생명주기** == 함수의 호출과 종료 (함수의 생명 주기) 9 | 10 | 전역 변수에서는 변수 선언이 런타임 이전에 실행되지만, 함수 내부에서 선언한 변수는 함수가 호출된 직후, 함수 몸체의 코드가 한 줄씩 순차적으로 실행되기 이전에 자바스크립트 엔진에 의해 먼저 실행. 11 | 12 | **변수의 생명 주기** 13 | - 메모리 공간이 확보된 시점 ~ 메모리 공간이 해제되어 가용 메모리 풀에 반환 14 | - 자신이 등록된 스코프가 소멸될 때까지 유효 15 | - 메모리 공간을 참조하고 있으면 해제되지 않고 확보된 상태로 남아있게 된다. 16 | 17 | ```javascript 18 | var x = 'global'; 19 | 20 | function foo(){ 21 | console.log(x); // 2. 지역변수 x 호출 -> x: undefined 22 | var x = 'local'; // 1. x 식별자 선언 / 3. x에 값 할당 23 | } 24 | 25 | foo(); 26 | console.log(x); 27 | ``` 28 | 29 | **호이스팅** 30 | - 스코프를 단위로 동작 31 | - 변수 선언이 스코프의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징 32 | 33 | ### 14.1.2 전역 변수의 생명 주기 34 | 전역 코드는 함수와 달리 명시적인 호출 없이 코드가 로드되자마자 곧바로 해석되고 실행됨. 전역 변수는 전역 객체의 프로퍼티가 되는데, 이는 곧 전역 변수의 생명 주기가 전역 객체의 생명주기와 일치한다는 것을 의미 35 | 36 | > 전역 객체 37 | > 코드가 실행되기 전에 자바스크립트 엔진에 의해 가장 먼저 생성되는 특수한 객체 38 | > 환경에 따라 객체를 가리키는 다양한 식별자가 존재했으나, ES11에서 globalThis로 통일됨 39 | 40 | ## 14.2 전역 변수의 문제점 41 | ### 암묵적 결합 42 | 전역 변수를 선언하는 의도 : 코드를 어디서든 참조하고 할당할 수 있는 변수로 사용하겠다 (= 암묵적 결합) 43 | 44 | ### 긴 생명 주기 45 | 전역 변수는 생명 주기가 길다 == 리소스를 오랜 기간 소비함. 46 | 또한 var는 변수의 중복 선언을 허용하므로 변수 이름의 중복 가능성이 높아짐. 47 | 48 | ### 스코프 체인 상에서 종점에 존재 49 | 종점에 존재 == 가장 마지막에 검색되어 검색 속도가 가장 느림 50 | 51 | ### 네임스페이스 오염 52 | 파일이 분리되어있다 해도 하나의 전역 스코프를 공유 53 | -> 다른 파일에서 동일한 이름으로 전역변수나 전역함수가 존재하는 경우, 예상치 못한 에러 발생 가능성 존재 54 | 55 | ## 14.3 전역 변수의 사용을 억제하는 방법 56 | 전역 변수를 반드시 사용해야 하는 이유가 없다면 지역 변수를 사용해야한다. 57 | 변수의 스코프는 작으면 작을 수록 좋음. 58 | 59 | ### 14.3.1 즉시 실행 함수 60 | 모든 코드를 즉시 실행 함수로 감싸면 모든 변수는 즉시 실행 함수의 지역 변수가 됨. 61 | (라이브러리 등에 주로 사용) 62 | 63 | ### 14.3.2 네임스페이스 객체 64 | 전역에 네임스페이스 역할을 하는 객체를 생성하고, 전역 변수처럼 사용하고 싶은 변수를 프로퍼티로 추가 65 | 66 | ```javascript= 67 | var MYAPP = {}; 68 | 69 | MYAPP.name = 'dana'; 70 | 71 | console.log(MYAPP.name); 72 | ``` 73 | 74 | 그 안에서 계층적으로 분리할 수 있다는 장점이 있으나, 결국 네임스페이스도 전역 변수의 프로퍼티로 선언된다는 단점이 있음. 75 | 76 | ### 14.3.3 모듈 패턴 77 | 클래스를 모방해서 관련있는 변수와 함수를 모아 즉시 실행 함수로 감싸 하나의 모듈 생성 78 | 클로저를 기반으로 동작하며 전역 변수의 억제, 캡슐화 구현 가능 79 | 80 | **캡슐화** 81 | `객체의 상태를 나타내는 프로퍼티`와 `프로퍼티를 참조하고 조작할 수 있는 동작인 메서드`를 하나로 묶는 것 82 | 정보은닉을 위해 사용되기도 함. 83 | 84 | 자바스크립트에서는 public, private, protected등의 접근 제한자를 제공하지 않기 때문에, 85 | 86 |
87 | 88 | 한번도 사용해보진 않았지만 private 접근 제한자가 생겼음 89 | 90 | 91 |

ECMAScript 2022, the 13th edition, the #x in obj syntax, to test for presence of private fields on objects;

92 | 93 |
94 | 95 | 96 | ```javascript= 97 | var Counter = (function() { 98 | // private 변수 99 | var num = 0; 100 | 101 | // 외부에 공개할 데이터나 메서드를 프로퍼티로 추가한 객체를 반환 102 | return { 103 | increase(){ 104 | return ++num; 105 | } 106 | } 107 | }()); 108 | 109 | console.log(Counter.num) // undefined 110 | console.log(Counter.increase()) // 1 111 | ``` 112 | 113 | Counter는 즉시실행함수가 반환한 객체값을 갖게됨. 114 | 115 | ### 14.3.4 ES6 모듈 116 | ES6 모듈을 사용하면 전역 변수 사용 불가능 117 | -> 파일 자체의 독자적인 모듈 프로세스를 제공하기 때문 118 | ```htmlmixed= 119 | 120 | ``` 121 | 122 | IE를 포함한 구형 브라우저에서는 동작하지 않음. 123 | -> ES6의 모듈 기능을 사용하지 못하는 경우에는 Webpack등의 모듈 번들러를 사용 124 | 125 | # 15. let, const 키워드와 블록 레벨 스코프 126 | ## 15.1 var 키워드로 선언한 변수의 문제점 127 | ### 15.1.1 변수 중복 선언 허용 128 | 129 | ```javascript= 130 | var x = 1; 131 | var y = 1; 132 | 133 | var x = 100; 134 | var y; 135 | 136 | console.log(x); // 100 137 | console.log(y); // 1 138 | ``` 139 | - `var x = 100;` : 초기화문에 있는 변수 선언문은 자바스크립트 엔진에 의해 var키워드가 없는 것처럼 동작 140 | - `var y;` : 초기화문이 없는 변수 선언문은 무시됨. 141 | 142 | ### 15.1.2 함수 레벨 스코프 143 | var키워드로 선언한 변수는 오로지 함수의 코드 블록만을 지역 스코프로 인정 144 | if문이나 for문 등에서 사용되는 var변수는 전역으로 선언되니 주의해서 사용하기 145 | 146 | ### 15.1.3 변수 호이스팅 147 | 변수 호이스팅에 의해 스코프의 선두로 끌어올려진 것처럼 동작 148 | 할당문 이전에 변수를 참조하면 undefined를 반환 149 | 150 | ## 15.2 let 키워드 151 | ### 15.2.1 변수 중복 선언 금지 152 | 변수 중복 선언이 SyntaxError 발생 153 | 154 | ### 15.2.2 블록 레벨 스코프 155 | let키워드로 선언한 변수는 모든 코드 블록을 지역스코프로 인정하는 블록레벨 스코프를 따름 156 | 157 | ### 15.2.3 변수 호이스팅 158 | let으로 선언한 변수는 변수 호이스팅이 발생하지 않는 것처럼 동작 159 | 변수 선언문 이전 참조시, ReferenceError 발생 160 | 161 | var로 선언한 변수는 선언 단계와 초기화 단계가 동시에 진행되지만, 162 | let으로 선언한 변수는 선언 단계와 초기화 단계가 분리되어 진행. 163 | 스코프 시작 지점부터 초기화 시작 지점까지 변수를 참조할 수 없는 구간을 **일시적 사각지대**하고 함. 164 | 165 | 변수 호이스팅이 발생하지 않는 것처럼 보이지만, 변수 호이스팅은 존재 166 | 167 | ```javascript= 168 | let foo = 1; 169 | 170 | { 171 | console.log(foo); // Reference Error 172 | let foo = 2; 173 | } 174 | ``` 175 | 176 | > 자바스크립트는 ES6에서 도입된 let , const 를 포함해서 모든 선언( var , let , const , function , 177 | function* , class 등)을 호이스팅한다. 단, ES6에서 도입된 let , const , class 를 사용한 선언문은 호이스 팅이 발생하지 않는 것처럼 동작한다. (????) 178 | 179 | 180 | ### 15.2.4 전역 객체와 let 181 | 전역 객체의 프로퍼티가 아니므로 window.x로 접근할 수 없음. 182 | 보이지 않는 개념적인 블록(전역 렉시컬 환경의 선언적 환경 레코드) 내에 존재 183 | 184 | ## 15.3 const 키워드 185 | 상수를 선언하기 위해 사용 186 | 키워드 특징은 let키워드와 비슷하게 동작 187 | 188 | ### 15.3.1 선언과 초기화 189 | const 키워드로 선언한 변수는 반드시 선언과 동시에 초기화해야 함. 190 | 그렇지 않으면 SyntaxError 발생 191 | 192 | ### 15.3.2 재할당 금지 193 | const 키워드로 선언한 변수는 재할당 금지~ 194 | 195 | ### 15.3.3 상수 196 | 원시 값을 할당한 경우 변수값을 변경할 수 없음. 197 | - 상태 유지 198 | - 가독성 199 | - 유지보수의 편의 200 | 위 특징들을 위해 상수를 적극적으로 활용 201 | 202 | 원시값을 할당한 경우, 원시값은 변경할 수 없는 값이고 const키워드에 의해 재할당이 금지되므로 할당된 값을 변경할 수 있는 방법이 없음 203 | 대부분 대문자로 선언해 상수임을 명확히 나타내고, 여러 단어로 이뤄진 경우 언더스코어로 구분해 스네이크 케이스로 표현 204 | 205 | ### 15.3.4 const 키워드와 객체 206 | const로 선언된 변수에 객체를 할당한 경우엔 값을 변경할 수 있음. 207 | 동적 생성, 삭제, 프로퍼티 값의 변경을 통해 객체를 변경하는 것은 가능 208 | 209 | ## 15.4 var vs let vs const 210 | - ES6 사용시 var 사용 X 211 | - 재할당이 필요한 경우에만 let 사용. 이 때 변수의 스코프는 최대한 좁게 212 | - 변경이 발생하지 않고 읽기 전용으로 사용하는 원시값과 객체에는 const 사용 213 | 214 | -> 일단 const를 사용하고 재할당이 필요하면 그 때 let으로 변경 215 | -------------------------------------------------------------------------------- /08) 16. 프로퍼티 어트리뷰트 & 17. 생성자 함수에 의한 객체 생성/June.md: -------------------------------------------------------------------------------- 1 | # 16. 프로퍼티 어트리뷰트 2 | 3 | ## 16.1 내부 슬롯과 내부 메서드 4 | 5 | 모든 객체는 `[[Prototype]]` 이라는 내부 슬롯을 갖는다. 내부 슬롯은 자바스크립트 엔진 내부 로직이므로 원래는 접근이 불가능하지만, `[[Prototype]]` 내부 슬롯은 예외적으로 `__proto__`를 통해서 접근이 가능하다. (던더 프로토) 6 | 7 | ## 16.2 프로퍼티 어트리뷰트와 프로퍼티 디스크립터 객체 8 | 9 | > 자바스크립트 엔진은 프로퍼티를 생성할 때 프로퍼티의 상태를 나타내는 프로퍼티 어트리뷰트를 기본값으로 자동 정의한다. 10 | 11 | ## 16.3 데이터 프로퍼티와 접근자 프로퍼티 12 | 13 | - 데이터 프로퍼티: 키와 값으로 구성된 일반적인 프로퍼티. 14 | - 접근자 프로퍼티: 자체적으론 값을 가지고 있지 않고, 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 호출되는 접근자 함수로 구성된 프로퍼티다. 15 | 16 | ### 16.3.1 데이터 프로퍼티 17 | 18 | - `[[Value]]`: 프로퍼티 키를 통해 접근하면 반환되는 값 19 | - `[[Writable]]`: 프로퍼티 값 변경 가능 여부 (불리언) 20 | - `[[Enumerable]]`: 프로퍼티 열거 가능 여부 (불리언) 21 | - `[[Configurable]]`: 프로퍼티 재정의 가능 여부 (불리언) 22 | 23 | ### 16.3.2 접근자 프로퍼티 24 | 25 | - `[[Get]]`: 접근자 프로퍼티를 통해 데이터 프로퍼티의 값을 읽을 때 호출되는 접근자 함수 26 | - `[[Set]]`: 접근자 프로퍼티를 통해 데이터 프로퍼티의 값을 저장할 때 호출되는 접근자 함수 27 | - `[[Enumerable]]`: 데이터 프로퍼티와 동일 28 | - `[[Configurable]]`: 데이터 프로퍼티와 동일 29 | 30 | `getter`, `setter` 함수라고도 부른다. 31 | 32 | ## 16.4 프로퍼티 정의 33 | 34 | > 프로퍼티 정의란 새로운 프로퍼티를 추가하면서 프로퍼티 어트리뷰트를 명시적으로 정의하거나, 기존 프로퍼티의 프로퍼티 어트리뷰트를 재정의하는 것을 말한다. 35 | 36 | 프로퍼티 디스크립터 객체의 프로퍼티 각각 생략했을 때의 기본 값 37 | 38 | - value, `[[Value]]`: `undefined` 39 | - get, `[[Get]]`: `undefined` 40 | - set, `[[Set]]`: `undefined` 41 | - writable, `[[Writable]]`: `false` 42 | - enumerable, `[[Enumerable]]`: `false` 43 | - configurable, `[[Configurable]]`: `false` 44 | 45 | ## 16.5 객체 변경 방지 46 | 47 | > 객체는 원래 변경 가능한 값이므로 재할당 없이 직접 변경할 수 있다. 즉, 갱신, 삭제, 추가, 프로퍼티 어트리뷰트를 재정의 할 수도 있다. 그래서 객체의 변경을 방지하는 다양한 메서드를 제공한다. 객체의 변경을 메서드들의 강도가 각각 다른데 살펴보자. 48 | 49 | - Object.preventExtensions 50 | - Object.seal 51 | - Object.freeze 52 | 53 | | 구분 | 메서드 | 프로퍼티 추가 | 프로퍼티 삭제 | 프로퍼티 값 읽기 | 프로퍼티 값 쓰기 | 프로퍼티 어트리뷰트 재정의 | 54 | | -------------- | -------------------------- | ------------- | ------------- | ---------------- | ---------------- | -------------------------- | 55 | | 객체 확장 금지 | `Object.preventExtensions` | X | O | O | O | O | 56 | | 객체 밀봉 | `Object.seal` | X | X | O | O | X | 57 | | 객체 동결 | `Object.freeze` | X | X | O | X | X | 58 | 59 | # 17. 생성자 함수에 의한 객체 생성 60 | 61 | ## 17.1 Object 생성자 함수 62 | 63 | ```javascript 64 | const person = new Object(); 65 | ``` 66 | 67 | 다른 string, number, array, boolean들도 생성자 함수를 제공한다. 68 | 하지만 리터럴 `{}`을 사용하는 것이 더 간편하다. 69 | 그래서 그닥 유용하지 않다고 한다. 70 | 71 | ## 17.2.3 생성자 함수의 인스턴스 생성 과정 72 | 73 | 1. 인스턴스 생성과 this 바인딩 74 | 75 | 암묵적으로 인스턴스가 생성되고, `this`에 바인딩된다. 76 | 77 | 2. 인스턴스 초기화 78 | 79 | 생성자 함수에 기술되어 있는 코드가 한 줄씩 실행되어 `this`에 바인딩되어 있는 인스턴스를 초기화한다. 80 | 81 | 3. 인스턴스 반환 82 | 83 | 생성자 함수 내부의 모든 처리가 끝나면 완성된 인스턴스가 바인딩된 `this`가 암묵적으로 반환된다. 84 | 만약 명시적으로 `return` 문을 명시한다면, `return` 문에 있는 객체가 반환된다. 85 | 원래 기본 동작은 `this`를 반환하는 것이라서 다른 객체를 `return` 한다면 기본 동작을 훼손하는 방법이다. 그래서 생성자 함수에서는 `return`문을 반드시 생략해야 한다. 86 | 87 | ## 17.2.4 `[[Call]]`, `[[Construct]]` 88 | 89 | ```javascript 90 | function foo() {} 91 | 92 | // 일반적인 함수로서 호출: [[Call]]이 호출 93 | foo(); 94 | 95 | // 생성자 함수로서 호출: [[Construct]]가 호출 96 | new foo(); 97 | ``` 98 | 99 | `[[Construct]]`를 갖지 않는 함수 객체를 non-constructor라고 부르고, 객체를 생성자 함수로서 호출할 수 없는 함수를 의미한다. 100 | 101 | `[[Call]]`을 가지면 callable이라고 하며 모든 함수 객체는 내부 메서드 `[[Call]]`을 다 가지고 있다. 102 | 103 | 함수 객체가 모두 `[[Construct]]`를 갖는 것은 아니기 때문에 constructor 일 수도 있고 non-constructor 일 수도 있다. 104 | 105 | ## 17.2.5 constructor와 non-constructor의 구분 106 | 107 | - constructor: 함수 선언문, 함수 표현식, 클래스(클래스도 함수다) 108 | - non-constructor: 메서드(ES6 메서드 축약 표현), 화살표 함수 109 | 110 | ## 17.2.6 new 연산자 111 | 112 | > `new` 연산자와 함께 함수를 호출하면 해당 함수는 생성자 함수로 동작한다. 단, `new` 연산자와 함께 호출하는 함수는 non-constructor가 아닌 constructor여야 한다. 113 | -------------------------------------------------------------------------------- /08) 16. 프로퍼티 어트리뷰트 & 17. 생성자 함수에 의한 객체 생성/README.md: -------------------------------------------------------------------------------- 1 | # 16. 프로퍼티 어트리뷰트 & 17. 생성자 함수에 의한 객체 생성 2 | 3 | ## 정리 4 | 5 | - [춘식]() 6 | - [뽀송 - 메인 발표자]() 7 | - [세인트](./saint.md) 8 | - [이안]() 9 | - [준]() 10 | - [다나]() 11 | -------------------------------------------------------------------------------- /09) 18. 함수와 일급객체/June.md: -------------------------------------------------------------------------------- 1 | # 18.1 일급 객체 2 | 3 | 일급 객체는 다음과 같은 조건을 만족한다. 4 | 5 | - 무명의 리터럴로 생성할 수 있다. 즉, 런타임에 생성이 가능하다. 6 | - 변수나 자료구조에 저장할 수 있다. (배열과 객체같은 곳) 7 | - 함수의 매개변수에 전달할 수 있다. 8 | - 함수의 반환값으로 사용할 수 있다. 9 | 10 | 그러니까 변수에 담을 수 있고, 반환 값으로 함수를 내뱉을 수도 있고, 어디서나 저장이 가능하면 일급 객체다. 11 | 자바스크립트의 함수는 위와 같이 사용할 수 있어서 **일급 객체**다. 12 | 13 | # 18.2 함수 객체의 프로퍼티 14 | 15 | 함수는 객체다. 그래서 프로퍼티를 가질 수 있다. 16 | `argumnets`, `caller`, `length`, `name`, `prototype` 프로퍼티는 모두 함수 객체의 데이터 프로퍼티다. 일반 객체에는 없고, 함수에만 고유하게 있는 프로퍼티다. 17 | 18 | `__proto__`는 단순히 접근자 프로퍼티이고, 함수 객체 고유의 프로퍼티가 아니다. 19 | `__proto__`는 `Object.prototype` 객체의 프로퍼티를 상속받은 것을 알 수 있다. 20 | `Object.prototype` 객체의 프로퍼티는 모든 객체가 상속받아 사용할 수 있다. 21 | 22 | ## 18.2.1 arguments 프로퍼티 23 | 24 | > 함수 객체의 arguments 프로퍼티 값은 arguments 객체이다. 해당 객체는 함수 호출 시 전달된 인수들의 정보를 담고 있는 순회 가능한 유사 배열이다. 함수 내부에서 지역변수처럼 쓰이고, 외부에선 사용 불가능이다. 25 | 26 | - 함수에 매개변수를 적게 전달해도, 많이 전달해도 자바스크립트는 무시하고 실행한다. (오류가 안 난다.) 27 | - 초과된 인수는 그냥 버려지는 것은 아니고, `arguments` 객체의 프로퍼티로 보관된다. 28 | - arguments는 배열이 아니라 **유사 배열 객체**라서 배열과 관련된 메소드를 사용하면 에러가 발생한다. 29 | 30 | ## 18.2.2 caller 프로퍼티 31 | 32 | > caller 프로퍼티는 ECMAScript 사양에 포함되지 않은 비표준 프로퍼티다. 이후 표준화될 예정도 없는 프로퍼티이므로 사용하지 말고 참고로만 알아두자. 관심이 없으면 지나쳐라. 33 | 34 | ## 18.2.3 length 프로퍼티 35 | 36 | > 함수 객체의 length 프로퍼티는 함수를 정의할 때 선언한 매개변수의 개수를 가리킨다. 37 | 38 | - arguments 객체의 length 프로퍼티는 인자(argument)의 개수를 가리키고, 함수 객체의 length 프로퍼티는 매개 변수(parameter)의 개수를 가리킨다. 39 | 40 | ```javascript 41 | function add(parameter1, parameter2) { 42 | arguments.length // 3 43 | } 44 | 45 | add(argument1, argument2, argument3); 46 | 47 | add.length // 2 48 | ``` 49 | 50 | ## 18.2.4 name 프로퍼티 51 | 52 | > 함수 객체의 name 프로퍼티는 함수 이름을 나타낸다. ES6에 표준이 됐다. 53 | 54 | - 익명 함수 표현식의 경우 ES5, ES6의 동작방식이 다르다. 55 | - ES5에서는 name 프로퍼티는 빈 문자열을 값으로 갖는다. 56 | - ES6에서는 함수 객체를 가리키는 식별자를 값으로 갖는다. 57 | 58 | ```javascript 59 | const anonymousFunc = function() {}; 60 | // ES5: anonymousFunc.name = 빈 문자열 61 | // ES6: anonymousFunc.name = anonymousFunc; 62 | ``` 63 | 64 | ## 18.2.5 __proto__ 접근자 프로퍼티 65 | 66 | > 모든 객체는 `[[Prototype]]` 이라는 내부 슬롯을 갖는다. 저 객체는 객체지향 프로그래밍의 상속을 구현하는 프로토타입 객체를 가리킨다. 67 | 68 | - `__proto__` 는 `[[Prototype]]` 내부 슬롯이 가리키는 프로토타입 객체에 접근하기 위해 사용하는 접근자 프로퍼티다. 69 | - 내부 슬롯에는 직접 접근은 불가능하고, 던더 프로토를 통해서 간접적으로 접근할 수 있다. 70 | 71 | ## 18.2.6 prototype 프로퍼티 72 | 73 | > prototype 프로퍼티는 생성자 함수로 호출할 수 있는 객체, 즉 constructor만이 소유하는 프로퍼티다. 74 | 일반 객체와 생성자 함수로 호출할 수 없는 non-constructor에는 prototype 프로퍼티가 없다. 75 | 76 | - prototype 프로퍼티는 함수가 객체를 생성하는 생성자 함수로 호출될 때 생성자 함수가 생성할 인스턴스의 프로토타입 객체를 가리킨다. -------------------------------------------------------------------------------- /09) 18. 함수와 일급객체/README.md: -------------------------------------------------------------------------------- 1 | # 18. 함수와 일급객체 2 | 3 | ## 정리 4 | 5 | - [춘식]() 6 | - [뽀송]() 7 | - [세인트 - 메인 발표자](saint.md) 8 | - [이안]() 9 | - [준]() 10 | - [다나]() 11 | -------------------------------------------------------------------------------- /09) 18. 함수와 일급객체/choonsik.md: -------------------------------------------------------------------------------- 1 | # 함수와 일급객체 2 | 3 | ## 일급 객체 4 | 5 | > 일급 객체란 6 | > 7 | > 1. 무명의 리터럴로 생성할 수 있다. 즉, 런타임에 생성이 가능하다. 8 | > 2. 변수나 자료구조에 저장할 수 있다. 9 | > 3. 함수의 매개변수에 전달할 수 있다. 10 | > 4. 함수의 반환값으로 사용할 수 있다. 11 | 12 | 자바스크립트의 함수는 일급 객체다. 13 | => 함수형 프로그래밍이 가능 14 | 15 | ## 함수 객체의 프로퍼티 16 | 17 | `console.dir` 18 | `Object.getOwnPropertyDescriptors()` 19 | 20 | 함수 객체 고유의 프로퍼티를 알아보자 21 | 22 | ### arguments 프로퍼티 23 | 24 | > 함수 객체의 arguments 프로퍼티 값은 arguments 객체 25 | > **arguments 객체** : 함수 호출 시 전달된 인수들의 정보를 담고 있는 순회 가능한 유사 배열 객체 26 | 27 | 자바스크립트는 함수의 매개변수와 인수의 개수가 일치하는지 확인하지 않는다. 28 | 29 | callee 프로퍼티 : arguments 객체를 생성한 함수 (자기 자신)을 가리킨다. 30 | length 프로퍼티 : 인수의 개수를 가리킨다. 31 | Symbol(Symbol.iterator) 프로퍼티 : arguments 객체를 순회 가능한 자료구조인 이터러블로 만들기 위한 프로퍼티 32 | 33 | ```js 34 | function symboltest(x, y) { 35 | const iterator = arguments[Symbol.iterator](); 36 | console.log(iterator.next()); // {value: 1, done: false} 37 | console.log(iterator.next()); // {value: 2, done: false} 38 | console.log(iterator.next()); // {value: undefined, done: true} 39 | 40 | return x * y; 41 | } 42 | symboltest(1, 2); 43 | ``` 44 | 45 | - `arguments` 객체 46 | - 가변 인자 함수를 구현할 때 유용하다. 47 | - 유사 배열 객체이다. (length 프로퍼티를 가진 객체. for문으로 순회할 수 있는 객체. 배열 메서드는 불가능) 48 | 49 | ```js 50 | function sum() { 51 | const array = Array.prototype.slice.call(arguments); 52 | return array.reduce(function (pre, cur) { 53 | return pre + cur; 54 | }, 0); 55 | } 56 | console.log(sum(1, 2)); // 3 57 | ``` 58 | 59 | ```js 60 | function sum(args...) { 61 | return args.redece((pre, cur) => pre + cur, 0); 62 | } 63 | ``` 64 | 65 | ### caller 프로퍼티 66 | 67 | > 함수 객체의 caller 프로퍼티는 함수 자신을 호출한 함수를 가리킨다. 68 | 69 | ```js 70 | function foo(func) { 71 | return func(); 72 | } 73 | 74 | function bar() { 75 | return "caller : " + bar.caller; 76 | } 77 | 78 | console.log(foo(bar)); // caller : function foo(func) {...} 79 | console.log(bar()); // caller : null 80 | ``` 81 | 82 | ### length 프로퍼티 83 | 84 | > 함수를 정의할 때 선언한 매개변수의 개수를 가리킨다. 85 | 86 | arguments 객체의 length : 인자의 개수 87 | 함수 객체의 length : 매개 변수의 개수 88 | 89 | ### name 프로퍼티 90 | 91 | > 함수 이름을 나타낸다. 92 | 93 | ```js 94 | var namedFunc = function foo() {}; 95 | console.log(namedFunc.name); // foo 96 | 97 | var anonymousFunc = function () {}; 98 | // ES5 : name 프로퍼티는 빈 문자열을 값으로 갖는다. 99 | // ES6 : name 프로퍼티는 함수 객체를 가리키는 변수 이름을 값으로 갖는다. 100 | console.log(anonymousFunc.name); // anonymousFunc 101 | 102 | function bar() {} 103 | console.log(bar.nae); // bar 104 | ``` 105 | 106 | ### `__proto__` 접근자 프로퍼티 107 | 108 | > 모든 객체는 [[Prototype]]이라는 내부 슬롯을 가지며, 이것은 객체지향 프로그래밍의 상속을 구현하는 프로토타입 객체를 가리킨다. 109 | 110 | `__proto__` 프로퍼티는 [[Prototype]] 내부 슬롯이 가리키는 프로토타입 객체에 간접적으로 접근하기 위해 사용하는 **접근자 프로퍼티**다. 111 | 112 | ```js 113 | const obj = { a: 1 }; 114 | 115 | // 객체 리터럴 방식으로 생성한 객체의 프로토타입 객체는 Object.prototype이다. 116 | console.log(obj.__proto__ === Object.prototype); // true 117 | 118 | // 객체 리터럴 방식으로 생성한 객체는 프로토타입 객체 Object.prototype 프로퍼티를 상속 받는다. 119 | // hasOwnProperty 메서드는 Object.prototype의 메서드다. 120 | console.log(obj.hasOwnProperty("a")); // true 121 | console.log(obj.hasOwnProperty("__proto__")); // false 122 | ``` 123 | 124 | ### prototype 프로퍼티 125 | 126 | > 생성자 함수로 호출할 수 있는 함수 객체, 즉 `constructor`만이 소유하는 프로퍼티 127 | 128 | ```js 129 | // 함수 객체는 prototype 프로퍼티를 소유한다. 130 | (function () {}).hasOwnProperty('prototype'); // true 131 | 132 | // 일반 객체는 prototype 프로퍼티를 소유하지 않는다. 133 | ({}).hasOwnProperty('property'); / false 134 | ``` 135 | 136 | prototype 프로퍼티는 함수가 객체를 생성하는 생성자 함수로 호출될 때 137 | 생성자 함수가 생성할 인스턴스의 **프로토타입 객체**를 가리킨다. 138 | -------------------------------------------------------------------------------- /09) 18. 함수와 일급객체/dana.md: -------------------------------------------------------------------------------- 1 | # 18. 함수와 일급 객체 2 | ## 18.1 일급 객체 3 | 1. 무명의 리터럴로 생성할 수 있다. (런타임 생성이 가능하다) 4 | 2. 변수나 자료구조에 저장할 수 있다. 5 | 3. 함수의 매개변수에 전달할 수 있다. 6 | 4. 함수의 반환값으로 사용할 수 있다. 7 | 8 | ```javascript= 9 | const ex1 = function(){ 10 | console.log("haha") 11 | } 12 | 13 | const ex2 = {ex1} 14 | 15 | function ex3(){ 16 | return function(){ 17 | console.log("hihi") 18 | } 19 | } 20 | ``` 21 | 22 | -> 자바스크립트의 함수는 다음 조건을 모두 만족하므로 일급객체다. 23 | = 함수를 **객체와 동일**하게 사용할 수 있다. 24 | 25 | 런타임에 함수 객체로 평가된다. 26 | 함수 객체는 일반 객체와 다르게 호출 가능하며, 고유의 프로퍼티를 소유한다는 차이점이 있다. 27 | 28 | ## 18.2 함수 객체의 프로퍼티 29 | console.dir을 이용해 함수 객체의 내부를 알 수 있다. 30 | 이를 Object.getOwnPropertyDescriptors 메서드로 확인해보면, arguments, caller, length, name, prototype 프로퍼티가 모두 함수 객체의 고유 프로퍼티인 것을 확인 할 수 있다. 하지만 **`proto`는 접근자 프로퍼티**이며, 함수 객체 고유의 프로퍼티가 아니라 Object.prototype 객체의 프로퍼티를 상속받은 것이다. (모든 객체가 사용할 수 있는 프로퍼티) 31 | 32 | ### 18.2.1 arguments 프로퍼티 33 | 함수 객체의 arguments 프로퍼티 값은 argument 객체 34 | - 함수 호출 시 전달된 인수들의 정보를 담고 있는 순회 가능한 유사 배열 객체 35 | - 함수 내부에서 지역 변수처럼 사용 (함수 외부에서 참조 불가능) 36 | 37 | 함수 정의 시, 선언한 매개변수는 함수 몸체 내부에서 변수와 동일하게 취급 38 | 함수 몸체 내에서 암묵적으로 매개변수가 선언 - undefined로 초기화 - 인수 할당 39 | 40 | 선언도니 매개 변수보다 인수를 적게 전달한 경우, undefined로 초기화된 상태를 유지 41 | 인수를 더 많이 작성한 경우, 암묵적으로 argument 객체의 프로퍼티로 보관 42 | 43 | arguments 객체의 callee 프로퍼티는 호출되어 arguments 객체를 생성한 함수 (자기 자신)을 가리키고, length 프로퍼티는 인수의 개수를 나타낸다. 44 | 45 | > arguments 객체의 Symbol(Symbol.iterator)프로퍼티 46 | > 순회 가능한 자료구조인 이터러블로 만들기 위한 프로퍼티 47 | > 추후 이터러블에서 더 자세하게 공부 48 | 49 | 선언된 매개변수의 개수와 함수를 호출할 때 전달하는 인수의 개수를 확인하지 않는 자바스크립트의 특성으로 인해 발생하는 오류를 막기 위해 arguments의 length 프로퍼티에 따라 달리 작동하도록 함수를 정의할 필요가 있다. 50 | 특히 **가변 인자 함수를 구현할 때 arguments.length를 사용하는 것이 유용**하다. 51 | 52 | arguments 객체는 유사배열객체 53 | -> 배열 메서드를 사용하는 경우 에러 발생 54 | 따라서 배열 배서드를 사용하고 싶다면, Function.prototype.call , Function.prototype.apply 를 사용해 간접 호출 해야함. 55 | -> 이런 번거로움을 해결하기 위해 ES6에서는 Rest 파라미터를 도입 56 | 57 | ### 18.2.2 caller 프로퍼티 58 | ECMAScript 사양에 포함되지 않는 비표준 프로퍼티 59 | 함수 객체의 caller 프로퍼티는 함수 자신을 호출한 함수를 가리킨다. 60 | 61 | ### 18.2.3 length 프로퍼티 62 | 함수를 정의할 때 선언한 매개변수의 개수 63 | arguments.length (넘겨받은 인자의 개수) != 함수 객체의 length (매개 변수의 개수) 64 | 65 | ### 18.2.4 name 프로퍼티 66 | ES5와 ES6에서 동작을 다르게 하므로 주의해야 한다. 67 | - 익명함수표현식 68 | - es5 : 빈 문자열 69 | - es6 : 함수 객체를 가리키는 식별자 70 | 71 | ### 18.2.5 `__proto__` 접근자 프로퍼티 72 | 모든 객체는 `[[Prototype]]` 이라는 내부 슬롯을 갖는데, 이는 객체지향 프로그래밍의 상속을 구현하는 프로토타입 객체를 가리킨다. 73 | 74 | 던더프로토(`__proto__`)는 내부 슬롯이 가리키는 프로토타입 객체에 접근하기 위해 사용하는 접근자 프로퍼티다. 75 | 76 | >#### hasOwnProperty 77 | > 78 | > 인수로 전달받은 프로퍼티키가 **객체 고유의 프로퍼티**인 경우에만 **true를 반환**하고 **상속받은 프로토타입의 프로퍼티 키**인 경우 **false** 반환 79 | 80 | ### 18.2.6 prototype 프로퍼티 81 | 생성자 함수로 호출할 수 있는 함수 객체(Constructor)만이 소유하는 프로퍼티 82 | -> 호출할 수 없는 경우(non-constructor)에는 prototype 프로퍼티가 없음. 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /10) 19. 프로토타입/June.md: -------------------------------------------------------------------------------- 1 | # 19. 프로토타입 2 | 3 | > 자바스크립트는 프로토타입 기반의 객체지향 프로그래밍 언어다. 4 | 5 | --- 6 | 7 | #### **클래스** 8 | 9 | 이 책에서는 클래스와 생성자 함수 모두 프로토타입 기반의 인스턴스를 생성하지만 정확히 동일하게 동작하지는 않다고 말하고, 클래스는 생성자 함수보다 엄격하고 생성자 함수에서 제공하지 않는 기능도 제공한다고 한다. 10 | 11 | 그래서 단순히 문법적 설탕이라고 보기에는 어렵고, 새로운 객체 생성 메커니즘으로 클래스를 바라보고 있다. 12 | 13 | --- 14 | 15 | 자바스크립트는 모든 것이 **객체**다. 그러면서 객체지향 프로그래밍에 대해서 설명하고 있다. 16 | 17 | ## 19.1 객체지향 프로그래밍 18 | 19 | > 객체지향 프로그래밍은 프로그램을 명령어 또는 함수의 목록으로 보는 전통적인 명령형 프로그래밍의 절차지향적 관점에서 벗어나 여러 개의 독립적 단위, 즉 객체(Object)의 집합으로 프로그램을 표현하려는 프로그래밍 패러다임을 말한다. 20 | 21 | - 객체의 다양한 속성 중에서 프로그램에 필요한 속성만 가추려 내어 표현하는 것을 **추상화**라고 한다. 22 | - 객체는 상태 데이터와 동작을 하나의 논리적인 단위로 묶은 **복합적인 자료구조**라고 할 수 있다. 23 | - 객체는 다른 객체와 메세지를 주고받거나 데이터를 처리할 수도 있다. 24 | - 객체는 다른 객체의 상태 데이터나 동작을 **상속**받아 사용하기도 한다. 25 | 26 | ## 19.2 상속과 프로토타입 27 | 28 | > 상속은 객체지향 프로그래밍의 핵심 개념으로, 어떤 객체의 프로퍼티 또는 메서드를 다른 객체를 상속받아 그대로 사용할 수 있는 것을 말한다. 29 | 30 | - 자바스크립트는 프로토타입을 기반으로 상속을 구현했고, 불필요한 중복을 제거했다. 31 | 32 | ```javascript 33 | function Circle(radius) { 34 | this.radius = radius; 35 | this.getArea = function () { 36 | return Math.PI * this.radius ** 2; 37 | }; 38 | } 39 | 40 | // 이렇게 하면 getArea 메서드가 중복 생성된다. 41 | // 같은 함수를 바라보는 것이 아니라, 객체 생성할 때마다 해당 메서드가 똑같이 생성된다. 42 | const circle1 = new Circle(1); 43 | const circle2 = new Circle(2); 44 | 45 | console.log(circle1.getArea === circle2.getArea); // false 46 | ``` 47 | 48 | 그래서 아래처럼 바꿀 수 있다. 49 | 50 | ```javascript 51 | function Circle(radius) { 52 | this.radius = radius; 53 | } 54 | 55 | // 미리 만들어놓은 함수를 공유해서 사용할 수 있도록 프로토타입에 추가한다. 56 | // 프로토타입 Circle 생성자 함수의 prototype 프로퍼티에 바인딩되어 있다. 57 | Circle.prototype.getArea = function () { 58 | return Math.PI * this.radius ** 2; 59 | }; 60 | 61 | // 모든 Circle 생성자 함수로 만든 인스턴스들은 부모 객체 역할을 하는 62 | // 프로토타입 Circle.prototype으로부터 getArea 메서드를 상속받는다. 63 | // 즉, Circle 생성자 함수가 생성하는 모든 인스턴스는 하나의 getArea 메서드를 공유한다. 64 | const circle1 = new Circle(1); 65 | const circle2 = new Circle(2); 66 | 67 | console.log(circle1.getArea === circle2.getArea); // true 68 | ``` 69 | 70 | 이렇게 상속은 코드의 재사용이라는 관점에서 매우 유용하다. 생성자 함수가 생성할 모든 인스턴스가 공통적으로 사용할 프로퍼티나, 메서드를 프로토타입에 미리 구현해 두면 생성자 함수가 생성할 모든 인스턴스는 별도의 구현 없이 상위 객체인 프로토타입의 자산을 공유하여 사용할 수 있다. 71 | 72 | ## 19.3 프로토타입 객체 73 | 74 | > 프로토타입 객체란 객체지향 프로그래밍의 근간을 이루는 객체 간 상속을 구현하기 위해 사용된다. 프로토타입은 어떤 객체의 상위 객체의 역할을 하는 객체로서 다른 객체에 공유 프로퍼티를 제공한다. 프로토타입을 상속받은 하위 객체는 상위 객체의 프로퍼티를 자신의 프로퍼티처럼 자유롭게 사용할 수 있다. 75 | 76 | - 모든 객체는 `[[Prototype]]` 내부 슬롯을 가지며, 이 내부 슬롯의 값은 프로토타입의 참조다. 77 | - `[[Prototype]]`에 저장되는 프로토타입은 객체 생성 방식에 의해 결정된다. 78 | - 모든 객체는 하나의 프로토타입을 갖는다. 그리고 모든 프로토타입은 생성자 함수와 연결되어 있다. 79 | - 프로토타입 체인의 종점, 최상위 객체는 Object.prototype 이며, 이 객체의 프로퍼티와 메서드는 모든 객체에 상속된다. 80 | 81 | ### 19.3.1 `__proto__` 접근자 프로퍼티 82 | 83 | #### `__proto__` 접근자 프로퍼티를 통해 프로토타입에 접근하는 이유 84 | 85 | > 상호 참조에 의해 프로토타입이 체인이 생성되는 것을 방지하기 위해서다. 86 | 87 | - 프로토타입 체인은 **단방향 링크드 리스트**로 구현되어야 한다. 88 | - 순환 참조하는 프로토타입 체인이 만들어지면 프로토타입의 체인 종점이 존재하지 않기 때문에 프로퍼티를 검색할 때 무한루프에 빠진다. 89 | 90 | #### `__proto__` 접근자 프로퍼티를 코드 내에서 직접 사용하는 것은 권장하지 않는다. 91 | 92 | - 모든 객체가 `__proto__` 접근자 프로퍼티를 사용할 수 있는 것은 아니기 때문에 권장하지 않는다. 93 | - Object.prototype을 상속받지 않는 객체를 생성할 수도 있기 때문에 `__proto__` 접근자 프로퍼티를 사용할 수 없는 경우가 있다. 94 | - 만약 프로포타입의 참조를 획득하고 싶다면 `Object.getPrototypeOf` 메서드를 사용하고, 프로토타입을 교체하고 싶다면 `Object.setPrototypeOf` 메서드를 사용하자. 95 | 96 | ### 19.3.2 함수 객체의 prototype 프로퍼티 97 | 98 | > 함수 객체만이 소유하는 `prototype` 프로퍼티는 생성자 함수가 생성할 인스턴스의 프로토타입을 가리킨다. 99 | 100 | - 함수 객체는 prototype 프로퍼티를 소유한다. 101 | - 일반 객체는 prototype 프로퍼티를 소유하지 않는다. 102 | - non-constructor인 화살표 함수와 ES6 메서드 축약 표현들도 prototype 프로퍼티를 소유하지 않는다. (constructor가 있어야 한다.) 103 | 104 | ### 19.3.3 프로토타입의 constructor 프로퍼티와 생성자 함수 105 | 106 | > 모든 프로토타입은 constructor 프로퍼티를 갖는다. 이 constructor 프로퍼티는 prototype 프로퍼티로 자신을 참조하고 있는 생성자 함수를 가리킨다. 이 연결은 생성자 함수가 생성될 때, 즉 함수 객체가 생성될 때 이뤄진다. 107 | 108 | ## 19.5 프로토타입의 생성 시점 109 | 110 | > 프로토타입은 생성자 함수가 생성되는 시점에 더불어 생성된다. 111 | 112 | ### 19.5.1 사용자 정의 생성자 함수와 프로토타입 생성 시점 113 | 114 | - 생성자 함수로서 호출할 수 있는 함수, 즉 constructor는 함수 정의가 평가되어 함수 객체를 생성하는 시점에 프로토타입도 더불어 생성된다. 115 | - 생성자 함수로서 호출할 수 없는 함수, 즉 non-constructor는 프로토타입이 생성되지 않는다. 116 | - 프로토타입도 객체이고 모든 객체는 프로토타입을 가지므로, 프로토타입도 자신의 프로토타입을 가지는데 그 객체는 Object.prototype이다. 117 | 118 | ### 19.5.2 빌트인 생성자 함수와 프로토타입 생성 시점 119 | 120 | > Object, String, Number, Function, Array, RegExp, Date, Promise와 같은 빌트인 생성자 함수도 일반 함수와 마찬가지로 빌트인 생성자 함수가 생성되는 시점에 프로토타입이 결정된다. 121 | 122 | - 객체가 생성되기 이전에 생성자 함수와 프로토타입은 이미 객체화되어 존재한다. 123 | - 이후 생성자 함수 또는 리터럴 표기법으로 객체를 생성하면 프로토타입은 생성된 객체의 `[[Prototype]]` 내부 슬롯에 할당된다. 124 | 125 | ## 19.6 객체 생성 방식과 프로토타입의 결정 126 | 127 | 객체는 다음과 같이 다양한 생성 방법이 있다. 128 | 129 | - 객체 리터럴 130 | - Object 생성자 함수 131 | - 생성자 함수 132 | - Object.create 메서드 133 | - 클래스(ES6) 134 | 135 | 각 방식마다 세부적인 객체 생성 방식의 차이는 있으나 추상 연산 `OrdinaryObjectCreate`에 의해 생성된다는 공통점이 있다. 136 | 137 | ### 19.6.1 객체 리터럴에 의해 생성된 객체의 프로토타입 138 | 139 | - 객체 리터럴 `const obj = {}`로 생성된 `obj` 객체는 Object.prototype을 프로토타입으로 갖게 되며, Object.prototype을 상속받는다. 140 | - `obj` 객체는 `constructor` 프로퍼티와 `hasOwnProperty` 같은 메서드 등을 소유하진 않지만, 자신의 프로토타입인 `Object.prototype`의 `constructor` 메서드와 `hasOwnProperty` 메서드를 자신의 자산인 것 처럼 사용할 수 있다. 141 | 142 | ### 19.6.2 Object 생성자 함수에 의해 생성된 객체의 프로토타입 143 | 144 | - 객체 리터럴과 동일하게 동작한다. 145 | - 차이점은 객체 리터럴 방식은 프로퍼티를 추가할 때 객체 리터럴 내부에 프로퍼티를 추가한다. 146 | - 하지만 Object 생성자 함수는 일단 빈 객체를 생성한 이후 프로퍼티를 추가해야 한다. 147 | 148 | ### 19.6.3 생성자 함수에 의해 생성된 객체의 프로토타입 149 | 150 | - new 연산자와 함께 생성자 함수를 호출하여 인스턴스를 생성하면 다른 객체 생성 방식과 마찬가지로 추상 연산 `OrdinaryObjectCreate`를 호출한다. 151 | - 이 때 `OrdinaryObjectCreate`에 전달되는 프로토타입은 생성자 함수의 prototype 프로퍼티에 바인딩되어 있는 객체다. 152 | - 사용자 정의 생성자 함수와 생성된 프로토타입의 프로퍼티는 `constructor` 뿐이다. 153 | 154 | ## 19.7 프로토타입 체인 155 | 156 | > 자바스크립트는 객체의 프로퍼티(메서드 포함)에 접근하려고 할 때 해당 객체에 접근하려는 프로퍼티가 없으면 `[[Prototype]]` 내부 슬롯의 참조를 따라 자신의 부모 역할을 하는 프로토타입의 프로퍼티를 순차적으로 검색한다. 이를 프로토타입 체인이라고 한다. 157 | 158 | - 프로토타입 체인의 종점인 `Object.prototype` 까지 프로퍼티 검색을 했는데 해당 프로퍼티가 없다면 `undefined`를 반환한다. 이 때 에러를 뱉지 않는다는 것에 주의하자. 159 | - 스코프 체인은 식별자 검색을 위한 메커니즘이고, 프로토타입 체인은 상속과 프로퍼티 검색을 위한 메커니즘이라고 보면된다. 160 | - 스코프 체인과 프로토타입 체인은 서로 연관없이 별도로 동작하는 것이 아니라 서로 협력하여 식별자와 프로퍼티를 검색하는 데 사용된다. 161 | 162 | ## 19.8 오버라이딩과 프로퍼티 섀도잉 163 | 164 | - 오버라이딩: 상위 클래스가 가지고 있는 메서드를 하위 클래스가 재정의하여 사용하는 방식 165 | - 오버로딩: 함수 이름은 동일하지만 매개변수의 타입 또는 개수가 다른 메서드를 구현하고 매개변수에 의해 메서드를 구별하여 호출하는 방식 166 | 167 | ## 19.10 instanceof 연산자 168 | 169 | - `객체 instanceof 생성자 함수` 형식으로 사용 가능하다. 170 | - `instanceof` 연산자는 프로토타입의 `constructor` 프로퍼티가 가리키는 생성자함수를 찾는 것이 아니라 생성자 함수의 `prototype`에 바인딩된 객체가 프로토타입 체인 상에 존재하는지 확인한다. 171 | 172 | ## 19.11 직접 상속 173 | 174 | ### 19.11.1 Object.create에 의한 직접 상속 175 | 176 | - Object.create 메서드는 명시적으로 프로토타입을 지정하여 새로운 객체를 생성한다. 177 | 178 | ### 19.11.2 객체리터럴 내부에서 **proto**에 의한 직접 상속 179 | 180 | - `__proto__`에 접근해서 직접 프로퍼티를 상속할 수 있다. 181 | 182 | ## 19.13 프로퍼티 존재 확인 183 | 184 | ### 19.13.1 in 연산자 185 | 186 | ```javascript 187 | // key in object 188 | const person = { 189 | name: "hyeonsu", 190 | address: "daejeon", 191 | }; 192 | 193 | console.log("name" in person); // true 194 | 195 | console.log("age" in person); // false 196 | ``` 197 | 198 | ## 19.14 프로퍼티 열거 199 | 200 | ### 19.14.1 for ... in문 201 | 202 | ```javascript 203 | for (변수선언문 in 객체) { ... } 204 | 205 | const person = { 206 | name: 'hyeonsu', 207 | address: 'daejeon', 208 | }; 209 | 210 | for (const key in person) { 211 | console.log(key); 212 | } 213 | 214 | // name 215 | // address 216 | ``` 217 | 218 | ### 19.14.2 Object.keys / values / entries 메서드 219 | -------------------------------------------------------------------------------- /10) 19. 프로토타입/README.md: -------------------------------------------------------------------------------- 1 | # 19. 프로토타입 2 | 3 | ## 정리 4 | 5 | - [춘식]() 6 | - [뽀송]() 7 | - [세인트](saint.md) 8 | - [이안 - 메인 발표자]() 9 | - [준]() 10 | - [다나]() 11 | -------------------------------------------------------------------------------- /10) 19. 프로토타입/choonsik.md: -------------------------------------------------------------------------------- 1 | # 프로토타입 2 | 3 | > 자바스크립트는 명령형, 함수형, 프로토타입 기반 객체지향 프로그래밍을 지원하는 멀티 패러다임 프로그래밍 언어다. 4 | 5 | - 클래스 6 | ES6에서 클래스가 도입되었다. 클래스도 함수이며, 기존 프로토타입 기반 패턴의 문법적 설탕이라고 볼 수 있지만 새로운 객체 생성 메커니즘으로 보는 것이 합당하다. 7 | 클래스와 생성자 함수는 모두 프로토타입 기반 인스턴스를 생성하지만, 클래스는 생성자 함수보다 더 엄격하고 다른 기능도 제공한다. 8 | 9 | - 객체 기반 프로그래밍 언어 10 | 자바스크립트를 이루고 있는 거의 모든 것(원시 타입 값을 제외한 나머지)이 객체다. 11 | 12 | ## 객체지향 프로그래밍 13 | 14 | > 여러 개의 독립적 단위, 즉 객체의 집합으로 프로그램을 표현하려는 프로그래밍 패러다임 15 | 16 | 속성 : 실체를 인식하고 구별하는 특징이나 성질 17 | 추상화 : 프로그램에 필요한 속성만 간추려 내어 표현하는 것 18 | 객체 : 속성을 통해 여러 개의 값을 하나의 단위로 구성한 복합적인 자료구조 19 | 20 | - 프로퍼티(상태) : 객체의 상채 21 | - 메서드(동작) : 상태 데이터 조작 22 | 23 | ## 상속과 프로토타입 24 | 25 | > 어떤 객체의 프로퍼티 또는 메서드를 다른 객체가 상속받아 그대로 사용할 수 있는 것 26 | 27 | 자바스크립트는 프로토타입을 기반으로 상속을 구현해 불필요한 중복을 제거한다. 28 | 중복을 제거하는 방법은 기존의 코드를 적극적으로 재사용하는 것이다. 29 | 30 | ## 프로토타입 객체 31 | 32 | > 객체 간 상속을 구현하기 위해 사용된다. 33 | > 프로토타입은 어떤 객체의 상위(부모) 객체의 역할을 하는 객체로서 다른 객체에 공유 프로퍼티를 제공한다. 34 | > 프로토타입을 상속받은 하위(자식) 객체는 상위 객체의 프로퍼티를 자신의 프로퍼티처럼 자유롭게 사용할 수 있다. 35 | 36 | 모든 객체는 [[Prototype]]이라는 내부 슬롯을 가지며, 37 | 객체가 생성될 때 객체 생성 방식에 따라 프로토타입이 결정되고 [[Prototype]]에 저장된다. 38 | 39 | 모든 객체는 하나의 프로토타입을 갖는다. 그리고 모든 프로토타입은 생성자 함수와 연결되어 있다. 40 | 41 | [[Prototype]] soqn tmffhtdpsms `__proto__` 접근자 프로퍼티를 통해 자신의 [[Prototype]] 내부 슬롯이 가리키는 프로토타입에 간접 접근 할 수 있다. 42 | 43 | 프로토타입은 자신의 constructor 프로퍼티를 통해 생성자 함수에 접근할 수 있고, 44 | 생성자 함수는 자신의 prototype 프토퍼티를 통해 프로토타입에 접근할 수 있다. 45 | 46 | ### **proto** 접근자 프로퍼티 47 | 48 | > 모든 객체는 **proto** 접근자 프로퍼티를 통해 자신의 프로토타입, 즉 [[Prototype]] 내부 슬롯에 간접적으로 접근할 수 있다. 49 | 50 | **`__proto__`는 접근자 프로퍼티다.** 51 | 내부 슬롯은 프로퍼티가 아니다. 52 | Object.prototype의 접근자 프로퍼티인 **proto**는 getter/setter 함수라고 부르는 접근자 함수를 통해 [[Prototype]] 내부 슬롯의 값(프로토타입)을 취득하거나 할당한다. 53 | 54 | **`__proto__` 접근자 프로퍼티는 상속을 통해 사용된다.** 55 | `__proto__` 접근자 프로퍼티는 객체가 직접 소유하는 프로퍼티가 아니라 Object.prototype의 프로퍼티다. 56 | 모든 객체는 상속을 통해 `Object.prototype.__proto__` 접근자 프로퍼티를 사용할 수 있다. 57 | 58 | #### Object.prototype 59 | 60 | 모든 객체는 프로포타입의 계층 구조인 프로토타입 체인에 묶여 있다. 61 | 자바스크립트 엔진은 객체의 프로퍼티에 접근하려고 할 때 해당 객체에 접근하려는 프로퍼티가 없다면 `__proto__` 접근자 프로퍼티가 가리키는 참조를 따라 자신의 부모 역할을 하는 프로토타입의 프로퍼티를 순차적으로 검색한다. 62 | 프로토타입 체인의 종점은 Object.prototype이며, 이 객체의 프로퍼티와 메서드는 모든 객체에 상속된다. 63 | 64 | **`__proto__` 접근자 프로퍼티를 통해 프로토타입에 접근하는 이유** 65 | 상호 참조에 의해 프로토타입 체인이 생성되는 것을 방지하기 위해서다. 66 | 프로토타입 체인은 단방향 링크드 리스트로 구현되어야 한다. (순환 참조 X) 67 | 68 | **`__proto__` 접근자 프로퍼티를 코드 내에서 직접 사용하는 것은 권장하지 않는다.** 69 | 70 | ### 함수 객체의 prototype 프로퍼티 71 | 72 | 함수 객체만이 소유하는 prototype 프로퍼티는 생성자 함수가 생성할 인스턴스의 프로토타입을 가리킨다. 73 | 모든 객체가 가지고 있는 `__proto__` 접근자 프로퍼티와 함수 객체만이 가지고 있는 prototype 프로퍼티는 결국 동일한 프로토타입을 가리키지만, 함수 객체의 사용 객체는 생성자 함수이다. 74 | 75 | ### 프로토타입의 constructor 프로퍼티와 생성자 함수 76 | 77 | 모든 프로토타입은 constructor 프로퍼티를 갖는다. 78 | 79 | ## 리터럴 표기법에 의해 생성된 생성자 함수와 프로토타입 80 | 81 | 리터럴 표기법에 의해 생성된 객체도 프로토타입이 존재하지만, constructor 프로퍼티가 가리키는 생성자 함수가 반드시 객체를 생성한 생성자 함수라고 단정할 수 없다. 82 | 83 | 객체 리터럴에 의해 생성된 객체는 Object 생성자 함수가 생성한 객체가 아니다. 84 | 85 | > 프로토타입과 생성자 함수는 단독으로 존재할 수 없다 언제나 쌍으로 존재한다. 86 | 87 | ## 프로토타입의 생성 시점 88 | 89 | > 프로토타입은 생성자 함수가 생성되는 시점에 더불어 생성된다. 90 | 91 | ### 사용자 정의 생성자 함수와 프로토타입 생성 시점 92 | 93 | 생성자 함수로서 호출할 수 있는 함수 constructor는 함수 정의가 평가되어 함수 객체를 생성하는 시점에 프로토타입도 더불어 생성된다. 94 | non-constructor는 프로토타입이 생성되지 않는다. 95 | 96 | ### 빌트인 생성자 함수와 프로토타입 생성 시점 97 | 98 | 모든 빌트인 생성자 함수는 전역 객체가 생성되는 시점에 생성된다. 99 | 생성된 프로토타입은 빌트인 생성자 함수의 prototype 프로퍼티에 바인딩된다. 100 | 101 | 객체가 생성되기 이전에 생성자 함수와 프로토타입은 이미 객체화되어 존재한다. 102 | 이후 생성자 함수 또는 리터럴 표기법으로 객체를 생성하면 프로토타입은 생성되 객체의 [[Prototype]] 내부 슬롯에 할당된다. 생성된 객체를 프로토타입을 상속받는다. 103 | 104 | ## 객체 생성 방식과 프로토타입의 결정 105 | 106 | 객체 생성 방법 107 | 108 | - 객체 리터럴 109 | - Object 생성자 함수 110 | - 생성자 함수 111 | - Object.create 메서드 112 | - 클래스 113 | 114 | 모두 추상 연산 `OrdinaryObjectCreate`에 의해 생성된다. 115 | 116 | 추상 연산 `OrdinaryObjectCreate`은 자신이 생성할 객체의 프로토타입을 인수로 전달받으며 프토퍼티 목록을 옵션으로 전달한다. 117 | 추상 연산 `OrdinaryObjectCreate`은 빈 객체를 생성하고 프로퍼티를 객체의 [[Prototype]] 내부 슬롯에 할당하고 객체를 반환한다. 118 | 119 | > 프로토타입은 추상 연산 `OrdinaryObjectCreate`에 전달되는 인수에 의해 결정된다. 120 | > 이 인수는 객체가 생성되는 시점에 객체 생성 방식에 의해 결정된다. 121 | 122 | ### 객체 리터럴에 의해 생성된 객체의 프로토타입 123 | 124 | > 객체 리터럴을 평가해 객체를 생성할 때 추상 연산 `OrdinaryObjectCreate`호출 125 | > 전달되는 프로토타입은 Object.prototype이다. 126 | 127 | ### Object 생성자 함수에 의해 생성된 객체의 프로토타입 128 | 129 | > 객체 리터럴과 마찬가지로 추상 연산 `OrdinaryObjectCreate`호출 130 | > 전달되는 프로토타입은 Object.prototype이다. 131 | > Object 방식은 일단 빈 객체를 생성한 후 프로퍼티를 추가해야 한다. 132 | 133 | ### 생성자 함수에 의해 생성된 객체의 프로토타입 134 | 135 | > 전달되는 프로토타입은 생성자 함수의 prototype 프로퍼티에 바인딩되어 있는 객체다. 136 | 137 | ## 프로토타입 체인 138 | 139 | > 자바스크립트는 객체의 프로퍼티(메서드 포함)에 접근하려 할 때 해당 객체에 접근하려는 프로퍼티가 없다면 [[Prototype]] 내부 슬롯의 참조를 따라 자신의 부모 역할을 하는 프로토타입의 프토퍼티를 순차적으로 검색한다. 이를 **프로토타입 체인**이라 한다. 프로토타입 체인은 자바스크립트가 객체지향 프로그래밍의 상속을 구현하는 매커니즘이다. 140 | 141 | - Object.prototype을 프로토타입 체인의 종점이라고 한다. Object.prototype의 프로토타입은 null이다. 142 | 143 | > 프로토타입 체인은 상속과 프로퍼티 검색을 위한 매커니즘이다. 144 | > 스코프 체인은 식별자 검색을 위한 매커니즘이다. 145 | > 스코프 체인과 프로토타입 체인은 서로 협력하여 식별자와 프로퍼티를 검색하는 데 사용된다. 146 | 147 | ## 오버라이딩과 프로퍼티 섀도잉 148 | 149 | 프로토타입이 소유한 프로퍼티를 프로토타입 프로퍼티, 150 | 인스턴스가 소유한 프로퍼티를 인스턴스 프로퍼티라고 부른다. 151 | 152 | 프로포타입 프로퍼티와 같은 이름의 프로퍼티를 인스턴스에 추가하면 프로토타입 체인을 따라 프로토타입 프로퍼티를 검색하여 인스턴스 프로퍼티로 추가한다. 153 | 154 | 상속 관계에 의해 프로퍼티가 가려지는 현상을 **프로퍼티 섀도잉**이라고 한다. 155 | 156 | 오버라이딩 : 상위 클래스가 가지고 있는 메서드를 하위 클래스가 재정의하여 사용하는 방식 157 | 오버로딩 : 함수 이름은 동일하지만 매개변수의 타입 또는 개수가 다른 메서드를 구현하고 매개변수에 의해 메서드를 구별하여 호출하는 방식. 158 | 159 | ## 프로토타입의 교체 160 | 161 | 프로토타입은 임의의 다른 객체를 변경할 수 있다. 162 | 부모 객체인 프로토타입을 동적으로 변경할 수 있다. 163 | 상속 관계도 동적으로 변경할 수 있으며, 프로토타입은 생성자 함수 또는 인스턴스에 의해 교체할 수 있다. 164 | 165 | ### 생성자 함수에 의한 프로토타입의 교체 166 | 167 | constructor 프로퍼티는 자바스크립트 엔진이 프로토타입을 생성할 때 암묵적으로 추가한 프로퍼티다. 168 | 프로토타입으로 교체한 객체 리터럴에는 constructor가 없다. 169 | 170 | ### 인스턴스에 의한 프로토타입의 교체 171 | 172 | 프로토타입은 생성자 함수의 prototype 프로퍼티뿐만 아니라 인스턴스의 `__proto__` 접근자 프로퍼티(Object.getPrototypeOf)를 통해 접근할 수 있ㅆ고 `__proto__` 접근자 프로퍼티(Object.setPrototypeOf)를 통해 교체할 수 있다. 173 | 174 | ## instanceof 연산자 175 | 176 | 객체 instanceof 생성자 함수 177 | 178 | 우변의 생성자 함수의 prototype에 바인딩된 객체가 좌변의 객체의 프로토타입 체인 상에 존재하면 true로 평가되고, 그렇지 않은 경우 false로 평가된다. 179 | 180 | 생성자 함수의 prototype에 바인딩된 객체가 프로토타입 체인 상에 존재하는지 확인한다. 181 | 182 | ## 직접 상속 183 | 184 | ### Object.create에 의한 직접 상속 185 | 186 | 명시적으로 프로토타입을 지정해 새로운 객체 생성. 187 | Object.create(생성할 객체의 프로토타입으로 지정할 객체, 생성할 객체의 프로퍼티 키와 프로퍼티 디스크럽터 객체) 188 | 189 | - new 연산자 없이 객체 생성 가능 190 | - 프로토타입을 지정하면서 객체 생성 가능 191 | - 객체 리터럴에 의해 생성된 객체도 상속 가능 192 | 193 | Object.create 메서드를 통해 프로토타입 체인의 종점에 위치하는 객체를 생성할 수 있다. 194 | 프로토타입 체인 종점에 위치하는 객체는 Object.prototype의 빌트인 메서드를 사용할 수 없다. 195 | 196 | ### 객체 리터럴 내부에서 **proto**에 의한 직접 상속 197 | 198 | 객체 리터럴 내부에서 `__proto__` 접근자 프로퍼티를 사용해 직접 상속을 구현할 수 있다. 199 | 200 | ## 정적 프로퍼티/메서드 201 | 202 | 생성자 함수로 인스턴스를 생성하지 않아도 참조/호출할 수 있는 프로퍼티와 메서드를 말한다. 203 | 204 | ## 프로퍼티 존재 확인 205 | 206 | ### in 연산자 207 | 208 | 객체 내에 특정 프로퍼티가 존재하는지 여부를 확인한다. 209 | 210 | ```js 211 | key in object; 212 | ``` 213 | 214 | 상속 받은 모든 프로토타입의 프로퍼티를 확인하므로 주의가 필요하다. 215 | 216 | ### Object.prototype.hasOwnProperty 메서드 217 | 218 | 객체에 특정 프로퍼티가 존재하는지 확인할 수 있다. 219 | 220 | ## 프로퍼티 열거 221 | 222 | ### for ... in 문 223 | 224 | 객체의 모든 프로퍼티를 순회하며 열거한다. 225 | 객체의 프로토타입 체인 상에 존재하는 모든 프로토타입의 프로퍼티 중에서 프로퍼티 어트리뷰트 값이 true인 프로퍼티를 순회하며 열거한다. 226 | 227 | 프로퍼티가 심벌인 프로퍼티는 열거하지 않는다. 228 | 229 | 상속받은 프로퍼티는 제외하려면 Object.prototype.hasOwnProperty 메서드를 사용해야 한다. 230 | 231 | 배열에는 일반적인 for 문이나 for --- of문 혹은 Array.prototype.forEach를 권장한다. 232 | 233 | ### Object.keys/values/entries 메서드 234 | 235 | 객체 자신의 고유 프로퍼티만 열거할 때 사용하자. 236 | 237 | Object.keys는 객체 자신의 열거 가능한 프로퍼티 키를 배열로 반환한다. 238 | Object.values는 객체 자신의 열거 가능한 프로퍼티 값을 배열로 반환한다. 239 | Object.entries는 객체 자신의 열거 가능한 프로퍼티 키와 값의 쌍의 배열을 배열에 담아 반환한다. 240 | -------------------------------------------------------------------------------- /10) 19. 프로토타입/dana(1).md: -------------------------------------------------------------------------------- 1 | # 19. 프로토타입 (1) 2 | 자바스크립트는 멀티 패러다임 프로그래밍 언어 3 | - 명령형 4 | - 함수형 5 | - 프로토타입 기반 6 | - 객체지향 프로그래밍 7 | 8 | 자바스크립트는 객체 기반의 프로그래밍 언어이며, 자바스크립트를 이루고 있는 대부분이 객체 (원시 타입 제외) 9 | 10 | ## 19.1 객체지향 프로그래밍 11 | 프로그램을 명령어 또는 함수의 목록으로 보는 전통적인 명령형 프로그래밍의 절차지향적 관점에서 벗어나 **여러 개의 독립적 단위(객체)의 집합**으로 프로그램을 표현하려는 프로그래밍 패러다임 12 | 13 | 실체를 철학적 사고로 인식하는 과정 14 | - 속성 : 실체의 특징이나 성질을 나타냄 15 | - 추상화 : 다양한 속정 중 프로그램에 필요한 속성만 간추려 내 표현하는 것 16 | - 객체 : 속성을 통해 여러개의 값을 하나의 단위로 구성한 복합적인 자료구조 / 상태 데이터와 동작을 하나의 논리적 단위로 묶은 복합적인 자료구조 17 | - 상태 : 데이터 18 | - 동작 : 상태 데이터를 조작 19 | 20 | ## 19.2 상속과 프로토타입 21 | 상속 : 어떤 객체의 프로퍼티 또는 메서드를 다른 객체가 상속받아 그대로 사용할 수 있는 것. 22 | 23 | 자바스크립트는 프로토타입을 기반으로 상속을 구현하여 기존의 코드를 적극적으로 재사용해 불필요한 중복을 제거한다. 24 | 25 | 생성자 함수가 생성한 모든 인스턴스는 자신의 상위 객체 Prototype의 모든 프로퍼티와 메서드를 상속받는다. 26 | 27 | ## 19.3 프로토타입 객체 28 | 객체지향 프로그래밍의 근간을 이루는 객체 간 상속을 구현하기 위해 사용 29 | 30 | 객체가 생성될 때 객체 생성방식에 따라 프로토타입이 결정되고, `[[prototype]]`에 저장된다. 31 | - 객체 리터럴에 의해 생성된 객체의 프로토타입 : Object.prototype 32 | - 생성자 함수에 의해 생성된 객체의 프로토타입 : 생성자 함수의 prototype 프로퍼티에 바인딩되어 있는 객체 33 | 34 | ### 19.3.1 `__proto__` 접근자 프로퍼티 35 | 모든 객체는 `__proto__` 접근자 프로퍼티를 통해 자신의 프로토타입 내부 슬롯에 간접적으로 접근할 수 있다. 36 | 37 | #### 1. `__proto__`는 접근자 프로퍼티다 38 | 자바스크립트는 원칙적으로 내부 슬록과 내부 메서드에 직접적으로 접근하거나 호출 할 수 있는 방법을 제공하지 않는다. `[[Prototype]]` 내부 슬록에도 직접 접근할 수 없ㅇ며, `__proto__` 접근자 프로퍼티를 통해 간접적으로 접근할 수 있게 된다. 39 | `__proto__`는 getter/setter 함수를 통해 프로토타입을 취득하거나 할당한다. 40 | 41 | #### 2. `__proto__` 접근자 프로퍼티는 상속을 통해 사용된다. 42 | 모든 객체는 상속을 통해 `Object.prototype.__proto__` 접근자 프로퍼티를 사용할 수 있다. 43 | 44 | #### 3. `__proto__` 접근자 프로퍼티를 통해 프로토타입에 접근하는 이유 45 | 프로토타입에 접근하기 위해 접근자 프로퍼티를 사용하는 이유는 **상호참조에 의해 프로토타입 체인이 생성되는 것을 방지하기 위해** 단방향 링크드 리스트로 구현되지 않으면 에러를 발생시킨다. 46 | 47 | #### 4. `__proto__` 접근자 프로퍼티를 코드 내에서 직접 사용하는 것은 권장하지 않는다. 48 | 모든 객체가 `__proto__` 접근자 프로퍼티를 사용할 수 있는 것은 아니기 때문에 권장하지 않는다. 49 | ex) 직접 상속을 통해 객체를 생성하는 경우 50 | 51 | -> `__proto__` 접근자 프로퍼티 대신 프로토타입의 참조를 취득하고 싶은 경우 Object.getPrototypeOf 메서드 사용 권장 52 | 53 | ### 19.3.2 함수 객체의 prototype 프로퍼티 54 | 함수 객체만이 소유하는 prototype 프로퍼티는 생성자 함수가 생성한 인스턴스의 프로토타입을 가리킨다. 55 | 56 | 모든 객체가 가지고 있는 `__proto__` 접근자 프로퍼티와 함수 객체만이 가지고 있는 prototype은 결국 동일한 프로토타입을 가리키지만, 프로퍼티를 사용하는 주체가 다르다. 57 | 58 | | 구분 | 소유 | 값 | 사용 주체 | 사용 목적 | 59 | |-----|----|---|----|---| 60 | | `__proto__` 접근자 프로퍼티 | 모든 객체 | 프로토타입의 참조 | 모든 객체 | 객체가 자신의 프로토타입에 접근 또는 교체하기 위해 사용 | 61 | |prototype 프로퍼티 | Constructor | 프로토타입의 참조 | 생성자 함수 | 생성자 함수가 자신이 생성할 객체의 프로토타입을 할당하기 위해 사용| 62 | 63 | ```javascript= 64 | function Person(name){ 65 | this.name = name; 66 | } 67 | 68 | const me = new Person('Lee'); 69 | console.log(Person.prototype === me.__proto__) // true 70 | ``` 71 | 72 | ### 19.3.3 프로토타입의 constructor 프로퍼티와 생성자 함수 73 | 모든 프로토타입은 constructor 프로퍼티를 갖는다. 이 프로퍼티는 prototype 프로퍼티로 자신을 참조하고 있는 생성자 함수를 가리킨다. 이 연결은 함수 객체가 생성될 때 이뤄진다. 74 | 75 | ## 19.4 리터럴 표기법에 의해 생성된 객체의 생성자 함수와 프로토타입 76 | constructor 프로퍼티가 가리키는 생성자 함수는 인스턴스를 생성한 생성자 함수 77 | 78 | **<-> 명시적으로 New 연산자를 사용하지 않는 객체 생성 방식** 79 | 80 | 이런 경우, constructor 프로퍼티가 가리키는 생성자 함수가 반드시 객체를 생성한 생성자 함수라고 단정할 수 없다. 81 | 82 | ```javascript= 83 | // 객체 리터럴 84 | const obj = {}; 85 | // 함수 리터럴 86 | const add = function (a , b) { return a + b; }; 87 | // 배열 리터럴 88 | const arr = [1 , 2 , 3]; 89 | // 정규 표현식 리터럴 90 | const regexp = /is/ig; 91 | ``` 92 | 93 | Object 생성자 함수에 인수를 전달하지 않거나, undefined, null을 인수로 전달하면서 호출하면 내부적으로는 추상 연산 `OrdinaryObjectCreate`를 호출하여 Object.prototype을 프로토타입으로 갖는 빈 객체를 생성한다. 94 | 95 | ```javascript= 96 | // 2. Object 생성자 함수에 의한 객체 생성 // 인수가 전달되지 않았을 때 추상 연산 OrdinaryObjectCreate를 호출하여 빈 객체를 생성한다. 97 | let obj = new Object(); 98 | console.log(obj); // {} 99 | 100 | 101 | // 1. new.target이 undefined나 Object가 아닌 경우 // 인스턴스  Foo.prototype  Object.prototype 순으로 프로토타입 체인이 생성된다. 102 | class Foo extends Object {} new Foo(); // Foo {} 103 | 104 | // 3. 인수가 전달된 경우에는 인수를 객체로 변환한다. 105 | // Number 객체 생성 106 | obj = new Object(123); 107 | console.log(obj); // Number {123} 108 | 109 | // String 객체 생성 110 | obj = new Object('123'); 111 | console.log(obj); // String {"123"} 112 | ``` 113 | 114 | 리터럴 표기법에 의해 생성된 객체도 상속을 위해 프로토타입이 필요하기 때문에, 생성된 객체도 가상적인 생성자 함수를 갖는다. **프로토타입과 생성자 함수는 단독으로 존재할 수 없고 항상 쌍으로 존재한다.** 115 | 116 | ## 19.5 프로토타입의 생성 시점 117 | 프로토타입은 생성자 함수가 생성되는 시점에 더불어 생성된다. 118 | 119 | ### 19.5.1 사용자 정의 생성자 함수와 프로토타입 생성 시점 120 | 생성자 함수로서 호출할 수 있는 함수(constructor)는 함수 정의가 평가되어 함수 객체를 생성하는 시점에 프로토타입도 더불어 생성 121 | 122 | `constructor`는 함수 정의가 평가되어 함수 객체를 생성 - `non-contructor`는 프로토타입이 생성되지 않는다. 123 | 124 | ### 19.5.2 빌트인 생성자 함수와 프로토타입 생성 시점 125 | 모든 빌트인 생성자 함수는 전역 객체가 생성되는 시점에 생성된다. 126 | 127 | 이후 생성자 함수 또는 리터럴 표시법으로 객체를 생성하면 프로토타입은 생성된 객체의 `[[Prototype]]` 내부 슬롯에 할당된다. 128 | 129 | ## 19.6 객체 생성 방식과 프로토타입의 결정 130 | 객체의 생성 방법 131 | - 객체 리터럴 132 | - Object 생성자 함수 133 | - 생성자 함수 134 | - Object.create 메서드 135 | - 클래스 136 | 137 | -> 추상 연산 OrdinaryObjectCreate에 의해 생성된다는 공통점이 있다. 필수적으로 자신이 생성할 객체의 프로토타입을 인수로 전달받고, 생성할 객체에 추가할 프로퍼티 목록을 옵션으로 전달할 수 있다. 138 | 139 | 즉, 객체가 생성되는 시점에 객체 생성 방식에 의해 결정되는 프로토타입 추상 연산 OrdinaryObjectCreate에 전달되는 인수에 의해 결정된다. 140 | 141 | ### 19.6.1 객체 리터럴에 의해 생성된 객체의 프로토타입 142 | 객체 리터럴을 평가하여 객체를 생성할 때 추상 연산 OrdinaryObjectCreate을 호출하는데, 여기에 전달되는 프로토타입은 Object.prototype이다. -> 객체 리터럴에 의해 생성되는 객체의 프로토타입은 **Object.prototype**이다. 143 | 144 | 객체 리터럴에 의해 생성된 객체는 constructor 프로퍼티와 hasOwnProperty 메서드 등을 소유하지 않지만, 자신의 프로토타입인 Object.prototype 객체를 상속 받았기 때문에 자신의 자산인 것처럼 자유롭게 사용할 수 있다. 145 | 146 | ### 19.6.2 Object 생성자 함수에 의해 생성된 객체의 프로토타입 147 | Object 생성자 함수를 인수없이 호출 시, 빈 객체가 생성된다. Object 생성자 함수를 호출하면 객체 리터럴과 마찬가지로 추상 연산 OrdinaryObjectCreater가 호출되며 Object 생성자 함수에 의해 생성되는 객체의 프로토타입은 **Object.prototype**이다. 148 | 149 | 객체 리터럴에 의해 생성된 객체와 동일한 구조를 갖지만, 프로퍼티를 추가하는 방식에서 차이가 나타난다. 150 | - 객체 리터럴 방식 : 객체 리터럴 내부에 프로퍼티를 추가 151 | - Object 생성자 함수 : 일단 빈 객체 생성 후 프로퍼티 추가 152 | 153 | ### 19.6.3 생성자 함수에 의해 생성된 객체의 프로토타입 154 | new 연산자와 함꼐 생성자 함수를 호출하여 인스턴스를 생성하면 OrdinaryObjectCreate가 호출되는데, 이 때 전달되는 프로토타입은 **생성자 함수의 prototype 프로퍼티에 바인딩되어 있는 객체**이다. 155 | 생성자 함수를 토앻 생성된 모든 객체는 프로토타입에 추가된 메서드를 상속 받아 자신의 메서드처럼 사용할 수 있다. 156 | 157 | ## 19.7 프로토타입 체인 158 | 자바스크립트는 객체의 프로퍼티에 접근할 때, 해당 객체에 찾는 프로퍼티가 없으면 159 | `[[Prototype]]` 내부 슬롯의 참조를 따라 자신의 부모 역할을 하는 프로토타입의 프로퍼티를 순차적으로 검색한다. 160 | 161 | 항상 최상위 프로토타입은 Object.prototype이다. 이를 프로토타입 체인의 종점이라고 한다. Object.prototype의 프로토타입은 null이다. 종점에서도 해당 프로퍼티 검색이 안되는 경우 undefined를 반환한다. 162 | 163 | > 스코프 체인 vs 프로토타입 체인 164 | > 165 | > 프로토타입 체인 : 상속과 프로퍼티 검색을 위한 매커니즘 166 | > 스코프 체인 : 식별자 검색을 위한 메커니즘 167 | 168 | 169 | -------------------------------------------------------------------------------- /11) 20. strict mode & 21. 빌트인 객체 & 22. this/JuneImage/rapper.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/11) 20. strict mode & 21. 빌트인 객체 & 22. this/JuneImage/rapper.jpeg -------------------------------------------------------------------------------- /11) 20. strict mode & 21. 빌트인 객체 & 22. this/README.md: -------------------------------------------------------------------------------- 1 | # 20. strict mode & 21. 빌트인 객체 & 22. this 2 | 3 | ## 정리 4 | 5 | - [춘식]() 6 | - [뽀송]() 7 | - [세인트]() 8 | - [이안]() 9 | - [준 - 메인 발표자]() 10 | - [다나]() 11 | -------------------------------------------------------------------------------- /11) 20. strict mode & 21. 빌트인 객체 & 22. this/choonti.md: -------------------------------------------------------------------------------- 1 | # strict mode 2 | 3 | ## strict mode란? 4 | 5 | 자바스크립트 언어의 문법을 좀 더 엄격히 적용해 오류를 발생시킬 가능성이 높거나 자바스크립트 엔진의 최적화 작업에 문제를 일으킬 수 있는 코드에 대해 명시적인 에러를 발생시킨다. 6 | 7 | ESLint 같은 린트 도구로도 유사한 효과를 얻을 수 있다. 8 | 9 | ## strict mode의 적용 10 | 11 | ```js 12 | `use strict`; 13 | ``` 14 | 15 | 위 코드를 사용하면 스크립트 전체에 strict mode가 적용된다. 16 | 17 | ## 전역에 strict mode를 적용하는 것은 피하자 18 | 19 | strict와 아닌 스크립트를 혼용하는 것은 오류를 발생시킬 수 있다. 20 | 외부 서드파티 라이브버리를 사용하는 경우 라이브러리가 non-strict-mode일 수 있으므로 실행 함수의 선두에 strict mode를 적용하는 등으로 사용하자. 21 | 22 | ## 함수 단위로 strict mode를 적용하는 것도 피하자 23 | 24 | 모든 함수에 일일이 적용하는 것이나, 외부 컨텍스트에 적용되어 있지 않는 경우 문제가 될 수 있으므로 즉시 실행 함수로 감싼 스크립트 단위로 적용하는 것이 바람직하다. 25 | 26 | ## strict mode가 발생시키는 에러 27 | 28 | ### 암묵적 전역 29 | 30 | 선언하지 않은 변수를 참조하면 ReferenceError 31 | 32 | ### 변수, 함수, 매개변수의 삭제 33 | 34 | delete 연산자로 변수, 함수, 매개변수를 삭제하면 SyntaxError 35 | 36 | ### 매개변수 이름의 중복 37 | 38 | 중복된 매개변수 이름 SyntaxError 39 | 40 | ### with 문의 사용 41 | 42 | SyntaxError. 동일한 객체의 프로퍼티를 반복해서 사용할 때 객체 이름을 생략할 수 있어서 성능과 가독성에 문제가 될 수 있다. 43 | 44 | ## strict mode 적용에 의한 변화 45 | 46 | ### 일반 함수의 this 47 | 48 | 함수를 일반 함수로 호출하면 this에 undefined가 바인딩된다. 49 | 50 | ### arguments 객체 51 | 52 | 매개변수에 전달된 인수를 재할당해도 arguments 객체에 반영되지 않는다. 53 | 54 | # 빌트인 객체 55 | 56 | ## 자바스크립트 객체의 분류 57 | 58 | - 표준 빌트인 객체 : 애플리케이션 전역의 공통 기능을 재공한다. 별도의 선언 없이 전역 변수처럼 언제나 참조할 수 있다. 59 | 60 | - 호스트 객체 : 브라우저 환경에서는 DOM, BOM 등 클라이언트 사이드 Web API를 호스트 객체로 제공하고 Node.js 환경에서는 Node.js의 API를 호스트 객체로 제공한다. 61 | 62 | - 사용자 정의 객체 : 사용자가 직접 정의한 객체 63 | 64 | ## 표준 빌트인 객체 65 | 66 | Object, String, Number, Boolean, Symbol, Date, Math, RegExp, Array, Map/Set, WeakMap/WeakSet, Function, Promise, Reflect, Proxy, JSON, Error 등 표준 빌트인 객체를 제공한다. 67 | 68 | Math, Reflect, JSON을 제외한 표준 빌트인 객체는 모두 인스턴스를 생성할 수 있는 생성자 함수 객체다. 생성자 함수 객체인 표준 빌트인 객체는 프로토타입 메서드와 정적 메서드를 제공하고 생성자 함수 객체가 아닌 표준 빌트인 객체는 정적 메서드만 제공한다. 69 | 70 | String, Number, Boolean, Function, Array, Date는 생성자 함수로 호출하여 인스턴스를 생성할 수 있다. 71 | 72 | 표준 빌트인 객체가 생성한 인스턴스의 프로토타입은 표준 빌트인 객체의 prototype 프로퍼티에 바인딩된 객체다. 73 | 74 | ## 원시값과 래퍼 객체 75 | 76 | 문자열, 슷자, 불리언 값에 대해 객체처럼 접근하면 생성되는 임시 객체를 래퍼 객체라 한다. 77 | 78 | ## 전역 객체 79 | 80 | 코드가 실행되기 이전 단계에 자바스크립트 엔진에 의해 어떤 객체보다도 먼저 생성되는 특수한 객체이며 어떤 객체에도 속하지 않은 최상위 객체 81 | 82 | globalThis는 모든 환경에서 사용하는 전역 객체를 말한다. 83 | 84 | 전역 객체는 표준 빌트인 객체와 환경에 따른 호스트 객체 그리고 var 키워드로 선언한 전역 변수와 전역 함수를 프로퍼티로 갖는다. 85 | 86 | - 개발자가 의도적으로 생성할 수 없다. 전역 객체를 생성할 수 있는 생성자 함수가 제공되지 안흔ㄴ다. 87 | - 전역 객체의 프로퍼티를 참조할 때 window(global)를 생략할 수 있다. 88 | 89 | - 전역객체는 모든 표준 빌트인 객체를 프로퍼티로 갖는다. 90 | 91 | - 자바스크립트 실행환경에 따라 추가적으로 프로퍼티와 메서드를 갖는다. 92 | 93 | - var 키워드로 선언한 전역 변수와 선언하지 않은 변수에 값을 할당한 암묵적 전역, 그리고 전역 함수는 전역 객체의 프로퍼티가 된다. 94 | 95 | - let, const 키워드 전역변수는 전역 객체의 프로퍼티가 아니다. 96 | 97 | - 브라우저 환경의 모든 자바스크립트 코드는 하나의 전역 객체 window를 공유한다. 98 | 99 | ## 빌트인 전역 프로퍼티 100 | 101 | 전역 객체의 프로퍼티를 말한다. 102 | Infinity, NaN, undefined 103 | 104 | ## 빌트인 전역 함수 105 | 106 | 애플리케이션 전역에서 호출할 수 있는 빌트인 함수로서 전역 객체의 메서드다. 107 | eval : 전달받은 문자열 코드가 표현식이라면 런타임에 평가하고, 아니라면 런타임에 실행한다. 기존의 스코프를 런타임에 동적으로 수정한다. 단 엄격모드에서는 자신의 자체적인 스코프를 생성한다. 보안과 최적화의 측면에서 사용을 금지하자 108 | 109 | isFinite 110 | isNaN 111 | parseFloat 112 | encodeURI/decodeURI는 URI의 문자들을 이스케이프 처리를 위해 인코딩/디코딩한다. 113 | encodeURIComponent/decodeURIComponent URI 구성 요소를 인코딩/디코딩한다. 인수를 쿼리 스트링의 일부로 간주해 =,?,&까지 인코딩한다는 점에서 다르다. 114 | 115 | ## 암묵적 전역 116 | 117 | 선언하지 않은 식별자에 값을 할당해 전역 객체의 프로퍼티가 되면 전역 변수처럼 동작한다. 이것은 변수가 아니므로 변수 호이스팅이 발생하지 않는다. 전역 변수와 달리 delete 연산자로 삭제할 수 있다. 118 | 119 | # this 120 | 121 | ## this 키워드 122 | 123 | 객체는 상태를 나타내는 프로퍼티와 동작을 나타내는 메서드를 하나의 논리적인 단위로 묶은 복합적인 자료구조다. 124 | 125 | 메서드가 자신의 객체 프로퍼티를 참조하려면 먼저 자신이 속한 객체를 가리키는 식별자를 참조할 수 있어야 한다. 126 | 127 | 재귀적인 참조는 바람직하지 않으므로, this라는 특수한 식별자가 존재한다. 128 | 129 | this는 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수다. this를 통해 자신이 속한 객체 또는 자신이 생성할 인스턴스의 프로퍼티나 메서드를 참조할 수 있다. 130 | 131 | this는 자바스크립트 엔진에 의해 암묵적으로 생성되며 코드 어디서든 참조할 수 있다. this가 가리키는 값, 즉 this의 바인딩은 함수 호출 방식에 의해 동적으로 결정된다. 132 | 133 | this 바인딩 : 식별자와 값을 연결하는 과정 134 | 135 | 자바스크립트의 this 함수가 호출되는 방식에 따라 this에 바인딩될 값, 즉 this 바인딩이 동적으로 결정된다. 136 | 일반적으로 객체의 메서드 내부, 생성자 함수 내부에서만 의미가 있다. 137 | 138 | ## 함수 호출 방식과 this 바인딩 139 | 140 | this바인딩은 함수 호출 방식, 즉 함수가 어떻게 호출되었는지에 따라 동적으로 결정된다. 141 | 142 | - 렉시컬 스코프와 this 바인딩은 결정 시기가 다르다. 143 | 144 | ### 일반 함수 호출 145 | 146 | 기본적으로 this에는 전역 객체가 바인딩된다. 147 | 일반 함수로 호출된 모든 함수 내부의 this에는 전역 객체가 바인딩된다. 148 | 149 | ### 메서드 호출 150 | 151 | 메서드 내부의 this는 메서드가 소유한 객체가 아닌 메서드를 호출한 객체에 바인딩된다. 152 | 153 | ### 생성자 함수 호출 154 | 155 | 생성자 함수 내부의 this에는 생성자 함수가 생성할 인스턴스가 바인딩된다. 156 | 157 | ### Function.prototype.apply/call/bind 메서드에 의한 간접 호출 158 | 159 | 이들 메서드는 모든 함수가 사용할 수 있으며 첫 번째 인수로 전달한 객체가 this바인딩된다. 160 | 161 | apply, call 메서드의 본질적인 기능은 함수를 호출하는 것이다. 162 | bind 메서드는 함수를 호출하지 않는다. 다만 첫 번째 인수로 전달한 값으로 this 바인딩이 교체된 함수를 새롭게 생성해 반환한다. 163 | bint 메서드는 this와 메서드 내부의 중첩 함수 또는 콜백 함수의 this가 불일치하는 문제를 해결하기 위해 유용하게 사용된다. 164 | -------------------------------------------------------------------------------- /12) 24. 클로저/Dana.md: -------------------------------------------------------------------------------- 1 | # 클로저 2 | 자바스크립트의 고유 개념이 아닌, 함수를 일급 객체로 취급하는 함수형 프로그래밍 언어에서 사용되는 중요한 특성 3 | > 클로저는 함수와 그 함수가 선언된 렉시컬 환경과의 조합 4 | 5 | #### 함수가 선언된 렉시컬 환경 6 | ```js 7 | const x = 1; 8 | 9 | function outerFunc(){ 10 | const x = 10; 11 | 12 | function innerFunc() { 13 | console.log(x); // 10 14 | } 15 | 16 | innerFunc(); 17 | // innerFunc이 outerFunc 함수 안에서 **정의**되었기 때문에, innerFunc의 상위스코프는 outerFunc 18 | // 만약 innerFunc가 정의된 것이 아니라 단순히 호출되었다면, innerFunc은 outerFunc의 변수 x에 접근할 수 없음. 19 | } 20 | 21 | outerFunc(); 22 | ``` 23 | 24 | ```js 25 | const x = 1; 26 | 27 | function outerFunc(){ 28 | const x = 10; 29 | 30 | innerFunc(); 31 | } 32 | 33 | function innerFunc() { 34 | console.log(x); // 1 35 | } 36 | 37 | outerFunc(); 38 | ``` 39 | 40 | ## 24.1 렉시컬 스코프 41 | 자바스크립트 엔진이 함수를 어디서 **호출**했는지가 아니라, 함수를 어디서 **정의**했는지에 따라 상위스코프를 결정하는 것. 42 | 이것에 의해 상위스코프는 정적으로 결정되고, 변하지 않음. 43 | 44 | > `스코프` = 실행컨텍스트의 렉시컬 환경 45 | `스코프 체인` = 외부 렉시컬 환경에 대한 참조를 통해 상위 렉시컬 환경과 연결됨 46 | 47 | ## 24.2 함수 객체의 내부 슬롯 `[[Environment]]` 48 | 49 | 상위 스코프를 기억하기 위해, 함수는 자신의 내부 슬롯 `[[Environment]]`에 참조를 저장한다. 50 | 51 | 함수 정의가 평가되어 함수 객체를 생성하는 시점 52 | = 상위스코프가 평가 또는 실행되고 있는 시점 53 | = 실행 중인 실행 컨텍스트 == 상위 스코프의 실행 컨텍스트 54 | 55 | 이 시점에 `[[Environment]]` 에 상위 스코프 참조가 할당됨. 56 | 57 | ## 24.3 클로저와 렉시컬 환경 58 | ```js 59 | const x = 1; 60 | 61 | function outer() { 62 | const x = 10; 63 | const inner = function () { console.log(x) }; 64 | return inner; 65 | } 66 | 67 | const innerFunc = outer(); 68 | // outer 함수를 호출하면 outer함수는 **중첩함수 inner를 반환하고** 생명 주기를 마감 69 | // 그리고 outer 함수의 실행 컨텍스트는 실행 컨텍스트 스택에서 팝되어 제거 됨. 70 | innerFunc(); 71 | ``` 72 | 73 | 외부 함수보다 중첩 함수가 더 오래 유지되는 경우 중첩 함수는 이미 생명 주기가 종료한 외부 함수의 변수를 참조 가능 -> 이 때 중첩 함수를 클로저라고 함. 74 | 실행 컨택스트에서 제거되어도 렉시컬 환경까지 소멸하는 것은 아님 75 | 76 | 자바스크립트의 모든 함수는 상위 스코프를 기억하므로 이론적으로 모든 함수는 클로저이지만, 상위스코프의 어떤 식별자도 참조하지 않는 함수는 클로저가 아님 77 | 이런 경우에는 브라우저 최적화를 통해 상위스코프를 기억하지 않음. 78 | 79 | 중첩함수가 외부함수보다 먼저 소멸되는 경우도 클로저라고 하지 않는다. 80 | 81 | > 만약 중첩 함수가 외부 함수의 모든 식별자를 사용하지 않는다면, 상위 스코프에는 사용하는 식별자만 저장됨. 이 때 사용되는 식별자를 `자유 변수`라고 부름. 82 | 83 | ## 24.4 클로저의 활용 84 | 상태를 안전하게 은닉하고 특정 함수에게만 상태 변경을 허용하기 위해 사용 85 | 86 | ### 예시 1) 87 | ```js 88 | // 카운트 상태 변수 89 | let num = 0; 90 | 91 | // 카운트 상태 변경 함수 92 | const increase = function() { 93 | // 카운트 상태를 1만큼 증가시킨다. 94 | return ++num; 95 | }; 96 | 97 | console.log(increase()); // 1 98 | console.log(increase()); // 2 99 | console.log(increase()); // 3 100 | ``` 101 | 102 | 1. 카운트 상태(num 변수의 값)는 increase 함수가 호출되기 전까지 변경되지 않고 유지되어야 한다. 103 | 2. 이를 위해 카운트 상태(num변수의 값)는 increase 함수만이 변경할 수 있어야 한다. 104 | 105 | 여기선 전역변수로 변수가 정의되어, 암묵적 결합이 일어남. 106 | > #### 암묵적 결합 107 | 전역 변수를 통해 관리되고 있기 때문에 언제든지 누구나 접근할 수 있고 변경할 수 있는 상태 108 | 109 | 따라서 지역변수로 값을 설정해 외부에서는 접근하지 못하도록 해야함. 110 | 111 | ### 예시 2) 112 | ```js 113 | const increase = function(){ 114 | let num = 0; 115 | 116 | return ++num; 117 | } 118 | 119 | // 이전 상태를 유지 하지 못한다. 120 | console.log(increase()); // 1 121 | console.log(increase()); // 1 122 | ``` 123 | 124 | ### 예시 3) 125 | ```js 126 | const increase = (function () { 127 | let num = 0; 128 | 129 | //클로저 130 | return function() { 131 | return ++num; 132 | }; 133 | }()); 134 | 135 | console.log(increase()); // 1 136 | console.log(increase()); // 2 137 | ``` 138 | 139 | ```js 140 | increase = function() { 141 | return ++num; 142 | }; // -> 상위 컨텍스트에 num에 대한 정보를 가지고 있음 143 | ``` 144 | 145 | 즉시 실행 함수가 반환한 클로저는 자신이 정의된 위치에 의해 결정된 상위 스코프인 즉시 실행 함수의 렉시컬 환경을 기억 146 | -> 즉시 실행 함수가 반환한 클로저는 카운트 상태를 유지하기 위한 자유 변수 num을 언제 어디서 호출하든지 참조하고 변경 가능 147 | 148 | 즉시 실행 함수는 한 번만 실행되므로 초기화될 일이 없고, 외부에서 접근 할 수 없으므로 안정적인 프로그래밍이 가능하다. 149 | 150 | 다른 기능도 추가하기 위해 다음과 같이 수정할 수 있음. 151 | ```js 152 | const counter = (function() { 153 | // 카운트 상태 변수 154 | let num = 0; 155 | 156 | // 클로저인 메서드를 갖는 객체를 반환 157 | // 객체 리터럴은 스코프를 만들지 않는다. 158 | // 따라서 아래 메서드들의 상위 스코프는 즉시 실행 함수의 렉시컬 환경 159 | return { 160 | increase() { 161 | return ++num; 162 | }, 163 | decrease() { 164 | return num > 0 ? --num : 0; 165 | } 166 | }; 167 | }()); 168 | 169 | console.log(counter.increase()); 170 | console.log(counter.decrease()); 171 | ``` 172 | 173 | 변수 값은 누군가에 의해 언제든지 변경될 수 있어 오류 발생 가능 174 | 외부 상태 변경이나 가변 데이터를 피하고 불변성을 지향하는 함수형 프로그래밍에서 부수 효과를 최대한 억제하여 오류를 피하고 프로그램의 안정성을 높이기 위해 클로저 사용 175 | 176 | ```js 177 | function makeCounter(aux){ 178 | let counter = 0; 179 | 180 | return function () { 181 | counter = aux(counter); 182 | return counter; 183 | }; 184 | } 185 | 186 | // 보조함수 187 | function increase(n) { 188 | return ++n; 189 | } 190 | 191 | // 보조함수 192 | function decrease(n) { 193 | return --n; 194 | } 195 | 196 | const increaser = makeCounter(increase) 197 | console.log(increaser()); // 1 198 | console.log(increaser()); // 2 199 | // 같은 increaser 함수끼리 렉시컬환경을 공유함 200 | 201 | const decreaser = makeCounter(decrease) 202 | console.log(decreaser()); // -1 203 | // 하지만 makeCounter가 새로 선언되었기 때문에 다른 렉시컬 환경을 공유함. 204 | ``` 205 | 206 | > makeCounter 함수를 호출해 함수를 반환할 때 반환된 함수는 자신만의 독립된 렉시컬 환경을 갖는다. 207 | 208 | ```js 209 | const counter = (function () { 210 | let counter = 0; 211 | 212 | return function (aux){ 213 | counter = aux(counter); 214 | 215 | return counter; 216 | }; 217 | }()); 218 | 219 | // 보조함수 220 | function increase(n) { 221 | return ++n; 222 | } 223 | 224 | // 보조함수 225 | function decrease(n) { 226 | return --n; 227 | } 228 | 229 | console.log(counter(increase)); 230 | ``` 231 | -> 자유 변수를 공유하게 됨. 232 | 233 | ### 모듈 패턴 234 | 네임스페이스 패턴에 렉시컬 스코프를 추가한 패턴 235 | 객체에 유효범위를 주어 캡슐화할 때 사용 236 | 237 | 가장 쉬운 방법은 객체 리터럴을 사용하는 것 238 | ```js 239 | function candy() { 240 | const name = 'kim'; 241 | const count = 10; 242 | 243 | return { 244 | addCandies : add => count + add, 245 | removeCandies : remove => count - remove, 246 | showCandies : () => {console.log(count)}, 247 | } 248 | } 249 | 250 | candy().addCandies(20); 251 | candy().showCandies() 252 | ``` 253 | 254 | 255 | ## 24.5 캡슐화와 정보 은닉 256 | `캡슐화` : 객체의 상태를 나타내는 프로퍼티와 프로퍼티를 참조하고 조작할 수 있는 동작인 메서드를 하나로 묶는 것 257 | `정보 은닉` : 객체의 특정 프로퍼티나 메서드를 감추는 것으로 의도치않게 상태가 변경되는 것을 막고, 객체 간 상호 의존성을 낮춤 258 | 259 | ```js 260 | const Person = (function () { 261 | let _age = 0; 262 | 263 | function Person(name , age){ 264 | this.name = name; 265 | _age = age; 266 | } 267 | 268 | Person.prototype.sayHi = function() { 269 | console.log(_age); 270 | } 271 | 272 | // 생성자 함수 반환 273 | return Person; 274 | }()); 275 | 276 | const me = new Person('kim', 20); 277 | me.sayHi() // 20 278 | console.log(me._age) // undefined 279 | ``` 280 | 281 | sayHi는 종료된 즉시실행함수의 지역변수 _age를 참조할 수 있는 클로저 282 | sayHi를 통해서만 age에 접근할 수 있다. 283 | 284 | 하지만 Person 객체간 _age의 값이 공유되지 않는 단점이 존재함. 285 | -> 자바스크립트는 정보 은닉을 완전하게 지원하지 않음 286 | 287 | ## 24.6 자주 발생하는 실수 288 | ```js 289 | var funcs =[]; 290 | 291 | for (var i = 0 ; i < 3 ; i++){ 292 | funcs[i] = function() {return i;} 293 | } 294 | 295 | for (var j = 0; j 내부 함수의 사용이 더이상 필요없는 경우, 외부변수를 초기화하여 메모리 할당을 해체시켜주는 것이 좋음. 309 | 310 | > 다른 더 자세한 내용은 [코어자바스크립트 : 클로저](https://velog.io/@deli-ght/%ED%81%B4%EB%A1%9C%EC%A0%80-%EC%BD%94%EC%96%B4%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-5#%ED%81%B4%EB%A1%9C%EC%A0%80%EC%9D%98-%EB%A9%94%EB%AA%A8%EB%A6%AC-%ED%95%B4%EC%A0%9C-%EC%98%88%EC%A0%9C) 참고하기! -------------------------------------------------------------------------------- /12) 24. 클로저/June.md: -------------------------------------------------------------------------------- 1 | # 24. 클로저 2 | 3 | > 클로저는 함수와 그 함수가 선언된 렉시컬 환경과의 조합이다. 4 | 5 | 요기서 핵심은 **함수가 선언된 렉시컬 환경**이다. 6 | 7 | # 24.1 렉시컬 스코프 8 | 9 | > 우리가 전에서 this는 호출될 때 결정된다면, 스코프는 선언, 즉 정의를 어디서 했느냐에 따라 결정된다. 10 | 11 | 사전적 의미는 **정적** 스코프이다. 그래서 함수를 어디 정의했는지에 따라 상위 스코프를 결정한다. 12 | 함수의 상위 스코프는 함수를 정의한 위치에 의해 정적으로 결정되고 변경되지 않는다. 13 | 14 | 렉시컬 스코프는 렉시컬 환경의 "외부 렉시컬 환경에 대한 참조"에 저장할 참조값, 즉 상위 스코프에 대한 참조는 함수 정의가 평가되는 시점에 함수가 정의된 환경(위치)에 의해 결정된다. 이것이 렉시컬 스코프다. 15 | 16 | # 24.2 함수 객체의 내부 슬롯 `[[Environment]]` 17 | 18 | 전역에 정의된 함수 선언문은 전역 코드가 평가되는 시점에 평가되어 함수 객체를 생성한다. 이 때 생성된 함수 객체의 내부 슬롯인 `[[Environment]]` 에는 함수 정의가 평가되는 시점, 즉 전역 코드 평가 시점에 실행 중인 실행 컨텍스트의 렉시컬 환경인 외부 함수 렉시컬 환경의 참조가 저장된다. 19 | 20 | 함수 객체의 내부 슬롯 `[[Environment]]`에 저장된 현재 실행 중인 실행 컨텍스트의 렉시컬 환경의 참조가 바로 상위 스코프다. 21 | 22 | 함수 호출 -> 함수 내부로 코드 제어권 이동 -> 함수 코드 평가 -> 함수 실행 컨텍스트 생성 -> 함수 렉시컬 환경 생성 (함수 환경 레코드 생성, this 바인딩, 외부 렉시컬 환경에 대한 참조 결정) 23 | 24 | # 24.3 클로저와 렉시컬 환경 25 | 26 | - 자바스크립트의 모든 함수는 자신의 상위 스코프를 기억한다. 모든 함수가 기억하는 상위 스코프는 함수를 어디서 호출하든 상관없이 유지된다. 따라서 함수를 어디든 호출하든 상관없이 함수는 언제나 자신이 기억하는 상위 스코프의 식별자를 참조할 수 있으며 식별자에 바인딩된 값을 변경할 수도 있다. 27 | - 사실 자바스크립트의 모든 함수는 상위 스코프를 기억하니까, 전부 클로저라고 볼 수 있지만 상위 스코프의 어떤 식별자도 참조하지 않는 함수는 클로저가 아니다. 28 | - 참조하지도 않는 식별자를 기억하는 것은 메모리 낭비이기 때문에 소멸시켜버린다. 29 | - 자신의 외부 식별자를 참조해서 클로저처럼 동작하고 있지만, 내부 함수가 반환이 되지 않는 경우도 있다. 그 경우에는 외부 함수보다 내부 함수가 더 생명주기가 짧으므로 클로저의 본질에 부합하지 않는다. 이 경우도 보통은 클로저라고 하지 않는다. 30 | 31 | 요기서 우리는 클로저 이름의 의미를 알 수 있다. **함수가 자유 변수에 대해 닫혀있다.**라는 의미이다. **자유 변수에 묶여있는 함수**라고 풀어 쓸 수 있다. 32 | 33 | # 24.4 클로저의 활용 34 | 35 | > 클로저는 상태를 안전하게 변경하고 유지하기 위해 사용한다. 다시 말해, 상태가 의도치 않게 변경되지 않도록 상태를 안전하게 은닉하고 특정 함수에게만 상태 변경을 허용하기 위해 사용한다. 36 | 37 | - 동일한 렉시컬 스코프를 가지고, 자유 변수를 공유하도록 설계와 코딩을 잘 해야한다. 38 | 39 | # 24.5 캡슐화와 정보 은닉 40 | 41 | > 캡슐화는 객체의 상태를 나타내는 프로퍼티와 프로퍼티를 참조하고 조작할 수 있는 동작인 메서드를 하나로 묶는 것을 말한다. 캡슐화는 객체의 특정 프로퍼티나 메서드를 감출 목적으로 사용하기도 하는데 이를 정보 은닉이라 한다. 42 | 43 | > 정보 은닉은 외부에 공개할 필요가 없는 구현의 일부를 외부에 공개되지 않도록 감추어 적절치 못한 접근으로부터 객체의 상태가 변경되는 것을 방지해 정보를 보호하고, 객체 간의 상호 의존성, 즉 결합도를 낮추는 효과가 있다. 44 | -------------------------------------------------------------------------------- /12) 24. 클로저/README.md: -------------------------------------------------------------------------------- 1 | # 24. 클로저 2 | 3 | ## 정리 4 | 5 | - [춘식]() 6 | - [뽀송]() 7 | - [세인트]() 8 | - [이안]() 9 | - [준]() 10 | - [다나 - 메인 발표자]() 11 | -------------------------------------------------------------------------------- /12) 24. 클로저/choonti.md: -------------------------------------------------------------------------------- 1 | # 클로저 2 | 3 | ## 렉시컬 스코프 4 | 5 | 자바스크립트 엔진은 함수를 어디서 호출했는지가 아니라 함수를 어디에 정의했는지에 따라 상위 스코프를 결정한다. 이를 렉시컬 스코프(정적 스코프)라 한다. 6 | 7 | 스코프의 실체는 실행 컨텍스트의 렉시컬 환경이다. 이 렉시컬 환경은 자신의 외부 렉시컬 환경에 대한 참조를 통해 상위 렉시컬 환경과 연결된다. 이것이 바로 스코프 체인이다. 8 | 9 | 함수의 상위 스코프를 결정한다는 것은 렉시컬 환경의 외부 렉시컬 환경에 대한 참조에 저장할 참조값을 결정한다는 것과 같다. 10 | 11 | 렉시컬 환경의 외부 렉시컬 환경에 대한 참조에 저장할 참조값, 12 | 즉 상위 스코프에 대한 참조는 함수 정의가 평가되는 시점에 함수가 정의된 환경에 의해 결정된다. 13 | 14 | ## 함수 객체의 내부 슬롯 15 | 16 | 함수는 자신의 내부 슬롯에 자신이 정의된 환경, 상위 스코프의 참조를 저장한다. 17 | 18 | 함수 객체의 내부 슬롯에 저장된 현재 실행 중인 실행 컨텍스트의 렉시컬 환경의 참조가 바로 상위 스코프다. 19 | 20 | - 함수 코드 평가 21 | 22 | 1. 함수 실행 컨텍스트 생성 23 | 2. 함수 렉시컬 환경 생성 24 | 2.1. 함수 환경 레코드 생성 25 | 2.2. this 바인딩 26 | 2.3. 외부 렉시컬 환경에 대한 참조 결정 27 | 28 | 외부 렉시컬 환경에 대한 참조에는 함수 객체의 내부 슬롯에 저장된 렉시컬 환경의 참조가 할당된다. 29 | 30 | ## 클로저와 렉시컬 환경 31 | 32 | 외부 함수보다 중첩 함수가 더 오래 유지되는 경우 중첩 함수는 이미 생명 주기가 종료한 외부 함수의 변수를 참조할 수 있다. 이러한 중첩 함수를 클로저라고 부른다. 33 | 34 | 클로저는 중첩 함수가 상위 스코프의 식별자를 참조하고 있고 중첩 함수가 외부 함수보다 더 오래 유지되는 경우에 한정하는 것이 일반적이다. 35 | 36 | 클로저에 의해 참조되는 상위 스코프의 변수를 자유 변수라고 부른다. 37 | 38 | ## 클로저의 활용 39 | 40 | 클로저는 상태를 안전하게 변경하고 유지하기 위해 사용한다. 상태를 안전하게 은닉하고 특정 함수에게만 상태 변경을 허용하기 위해 사용한다. 41 | 42 | ## 캡슐화와 정보 은닉 43 | 44 | 캡슐화는 객체의 상태를 나타내는 프로퍼티와 프로퍼티를 참조하고 조작할 수 있는 동작인 메서드를 하나로 묶는 것을 말한다. 캡슐화는 객체의 특정 프로퍼티나 메서드를 감출 목적으로 사용하는 것을 정보 은닉이라 한다. 45 | 46 | 정보 은닉은 객체 간의 상호 의존성, 결합도를 낮추는 효과가 있다. 47 | 48 | 자바스크립트는 정보 은닉을 완전하게 지원하지는 않지만, 클래스에 private 필드를 정의할 수 있는 새로운 표준 사양이 제안되었다. 49 | -------------------------------------------------------------------------------- /13) 25. 클래스/June.md: -------------------------------------------------------------------------------- 1 | # 25. 클래스 2 | 3 | # 25.1 클래스는 프로토타입의 문법적 설탕인가? 4 | 5 | > 자바스크립트 프로토타입의 언어이기 때문에 객체 지향적인 클래스가 필요없었다. 6 | 7 | 클래스와 생성자 함수가 다른 점 8 | 9 | 1. 클래스를 new 연사자 없이 호출하면 에러가 발행한다. 하지만 생성자 함수를 new 연산자 없이 호출하면 일반 함수로서 호출된다. 10 | 2. 클래스는 상속을 지원하는 extends와 super 키워드를 제공한다. 하지만 생성자 함수는 extends와 super 키워드를 지원하지 않는다. 11 | 3. 클래스는 호이스팅이 발생하지 않는 것처럼 동작한다. 하지만 함수 선언문으로 정의된 생성자 함수는 함수 호이스팅이 발생한다. 12 | 4. 클래스 내의 모든 코드에는 암묵적으로 strict mode가 지정되어 실행되며 strict mode를 해제할 수 없다. 하지만 생성자 함수는 암묵적으로 strict mode가 지정되지 않는다. 13 | 5. 클래스의 컨스트럭트, 프로토타입 메서드, 정적 메서드는 모두 프로퍼티 어트리뷰트 `[[Enumerable]]`의 값이 false다. 다시 말해, 열거되지 않는다. 14 | 15 | # 25.2 클래스 정의 16 | 17 | > 클래스는 class 키워드를 사용하여 정의한다. 18 | 19 | 클래스는 일급 객체로서 밑의 특징을 가진다. 20 | 21 | 1. 무명의 리터럴로 생성할 수 있다. 즉, 런타임에 생성이 가능하다. 22 | 2. 변수나 자료구조에 저장할 수 있다. 23 | 3. 함수의 매개변수에게 전달할 수 있다. 24 | 4. 함수의 반환값으로 사용할 수 있다. 25 | 26 | 클래스 몸체에는 0개 이상의 메서드만 정의할 수 있다 27 | 28 | - constructor (생성자) 29 | - 프로토타입 메서드 30 | - 정적 메서드 31 | 32 | # 25.3 클래스 호이스팅 33 | 34 | > 클래스는 함수로 평가된다. 35 | 36 | - 클래스 선언문으로 정의한 클래스는 함수 선언문과 같이 소스코드 평가 과정, 즉 런타임 이전에 먼저 평가되어 함수 객체를 생성한다. 이 때 클래스가 평가되어 생성된 함수 객체는 생성자 함수로서 호출할 수 있는 함수 즉 constructor다. 37 | - 클래스는 클래스 정의 이전에 참조할 수 없다. 38 | - 클래스는 `let`, `const` 키워드로 선언한 변수처럼 호이스팅된다. 39 | - 그래서 클래스도일시적 사각지대에 빠질 수 있다. 40 | 41 | # 25.4 인스턴스 생성 42 | 43 | > `new` 연산자와 함께 호출되어서 인스턴스를 생성할 수 있다. 44 | 45 | - `new` 연산자를 사용하지않으면 타입 에러가 발생한다. 46 | 47 | # 25.5 메서드 48 | 49 | > 클래스 몸체에서 정의할 수 있는 메서드는 constructor(생성자), 프로토타입 메서드, 정적 메서드 세 가지가 있다. 50 | 51 | ## 25.5.1 constructor 52 | 53 | > constructor는 인스턴스를 생성하고 초기화하기 위한 특수한 메서드다. constructor는 이름을 변경할 수 없다. 54 | 55 | - constructor안에서 this에 추가한 프로퍼티는 인스턴스 프로퍼티가 된다. 56 | - 생성자 === constructor 57 | 58 | 클래스가 생성한 인스턴스에는 생성자 메서드가 보이지 않는다. 이는 생성자 함수가 단순한 메서드가 아니란 뜻이다. 59 | 생성자는 메서드로 해석되는 것이 아니라 클래스가 평가되어 생성한 함수 객체 코드의 일부가 된다. 60 | 61 | 생성자에는 몇 가지 특징이 있다. 62 | 63 | - 생성자 메서드는 클래스 내 최대 한 개만 존재할 수 있다. 64 | - 생성자 메서드는 생략할 수 있다. 65 | - 인스턴스를 초기화하려면 생성자 메서드를 생략하면 안된다. 66 | - 생성자 메서드는 반환문이 없다. 암묵적으로 this, 즉 인스턴스를 반환한다. 67 | - 만약 return을 쓴다면 this 반환이 무시된다. (반드시 하면 안되는 행동) 68 | 69 | ## 25.5.2 프로토타입 메서드 70 | 71 | > 클래스 몸체에 일반적으로 생성한 메서드는 프로토타입 메서드가 된다. 72 | 73 | - 생성자 함수와 마찬가지로 클래스가 생성한 인스턴스는 프로토타입 체인의 일원이 된다. 74 | - 인스턴스는 프로토타입 메서드를 상속받아서 사용할 수 있다. 75 | 76 | ## 25.5.3 정적 메서드 (몰랐음) 77 | 78 | > 정적 메서드는 인스턴스를 생성하지 않아도 호출할 수 있는 메서드다. `static` 키워드를 붙이면 된다. 79 | 80 | - 정적 메서드는 클래스에 바인딩된 메서드가 된다. 프로토타입 메서드는 프로토타입에 들어간다. 81 | - 정적 메서드는 클래스 정의 이후에 인스턴스를 생성하지 않아도 호출할 수 있다. 82 | - 정적 메서드는 인스턴스로 호출할 수 없다. 왜냐하면 프로토타입 체인상에 존재하지 않기 때문 83 | 84 | ## 25.5.4 정적 메서드와 프로토타입 메서드의 차이 85 | 86 | 1. 자신이 속해 있는 프로토타입 체인이 다르다. 87 | 2. 정적 메서드는 클래스로 호출, 프로토타입 메서드는 인스턴스로 호출한다. 88 | 3. 정적 메서드는 인스턴스 프로퍼티를 참조할 수 없지만 프로토타입은 참조할 수 있다. 89 | 90 | ## 25.5.5 클래스에서 정의한 메서드의 특징 91 | 92 | 1. function 키워드를 생략한 메서드 축약표현을 사용한다. 93 | 2. 암묵적으로 strict mode가 실행 94 | 3. for ... in 문이나 Object.keys와 같은 메서드 등으로 열거할 수 없다. 95 | 4. `new` 연산자와 함께 호출할 수 없다. 96 | 97 | # 25.6 클래스의 인스턴스 생성 과정 98 | 99 | 1. 인스턴스 생성과 this 바인딩 - 인스턴스는 this에 바인딩된다. 100 | 2. 인스턴스 초기화 - this에 바인딩되어 있는 인스턴스를 초기화한다. 프로퍼티도 초기화 한다. 만약 생성자가 없으면 이 과정이 생략된다. 101 | 3. 인스턴스 반환 - 완성된 인스턴스가 바인딩된 this가 암묵적으로 반환된다. 102 | 103 | # 25.7 프로퍼티 104 | 105 | ## 25.7.1 인스턴스 프로퍼티 106 | 107 | > 인스턴스 프로퍼티는 constructor 내부에서 정의해야 한다. 108 | 109 | - 기본적으로 Public 이다. 110 | - constructor안에서 private, public, protected와 같은 키워드와 같은 접근 제한자를 지원하지 않는다. 111 | 112 | ## 25.7.2 접근자 프로퍼티 113 | 114 | - getter, setter와 함수를 제공한다. 115 | - setter는 딱 하나의 매개변수만 선언 가능하다. 116 | 117 | ## 25.7.3 클래스 필드 정의 제안 118 | 119 | - 인스턴스를 생성할 때 클래스 필드를 초기화할 필요가 있다면 constructor 밖에서 클래스 필드를 정의할 필요가 없다. 120 | 121 | ## 25.7.4 private 필드 정의 제안 122 | 123 | - 인스턴스 프로퍼티는 항상 Pulbic이기 때문에 private로 선언할 것이 필요했다. 124 | - `#` 키워드를 필드 앞에 붙이면된다. 125 | 126 | ## 25.7.5 static 필드 정의 제안 127 | 128 | - 프로퍼티에도 static을 붙일 수 있다. 129 | 130 | # 25.8 상속에 의한 클래스 확장 131 | 132 | # 25.8.1 클래스 상속과 생성자 함수 상속 133 | 134 | - 상속에 의한 클래스 확장은 기존 클래스를 상속받아 새로운 클래스를 확장하여 정의하는 것이다. 135 | - extends 키워드를 사용해서 상속하고 받을 수 있다. 136 | 137 | # 25.8.2 extends 키워드 138 | 139 | - 상속을 통해 클래스를 확장하려면 extends 키워드를 사용하여 상속받을 클래스를 정의한다. 140 | - 상속을 통해 확장된 클래스를 서브클래스, 서브클래스에게 상속된 클래스를 수퍼클래스라 부른다. 141 | - 서브클래스를 자식클래스, 수퍼클래스를 부모클래스라고 부르기도 한다. 142 | 143 | # 25.8.5 super 키워드 144 | 145 | > super 키워드는 함수처럼 호출할 수도 있고, this와 같이 식별자처럼 참조할수 있는 특수한 키워드다 146 | 147 | super의 동작방식은 아래와 같다. 148 | 149 | - super를 호출하면 수퍼클래스(부모)의 constructor를 호출한다. 150 | - super를 참조하면 수퍼클래스(부모)의 메서드를 호출할 수 있다. 151 | 152 | 만약에 상속을 받는 서브클래스는 자동적으로 부모클래스의 super를 실행시켜서 constructor가 실행이 되는 것이다. 153 | 154 | super를 호출할 때 주의할 점은 다음과 같다. 155 | 156 | - 자식클래스에서 constructor를 생략하지 않는 경우 자식클래스의 constructor에서는 반드시 super를 호출해야 한다. 157 | - 자식클래스의 constructor에서 super를 호출하기 전에는 this를 참조할 수 없다. 158 | - super는 반드시 자식클래스의 constructor에서만 호출한다. 자식클래스가 아닌 클래스의 constructor나 함수에서 super를 호출하면 에러가 발생한다. 159 | 160 | # 25.8.6 상속 클래스의 생성 과정 161 | 162 | 1. 자식 클래스의 super 호출 163 | 2. 부모 클래스의 인스턴스 생성과 this 바인딩 164 | 3. 부모 클래스의 인스턴스 초기화 (부모 클래스 constructor 실행) 165 | 4. 자식 클래스 constructor로의 복귀와 this 바인딩 166 | 5. 자식 클래스 인스턴스 초기화 (자식 클래스 constructor 실행) 167 | 6. 인스턴스 최종 반환 168 | -------------------------------------------------------------------------------- /13) 25. 클래스/README.md: -------------------------------------------------------------------------------- 1 | # 25. 클래스 2 | 3 | ## 정리 4 | 5 | - [춘식 - 메인 발표자]() 6 | - [뽀송]() 7 | - [세인트]() 8 | - [이안]() 9 | - [준]() 10 | - [다나]() 11 | -------------------------------------------------------------------------------- /14) 26. 함수의 추가 기능/Dana.md: -------------------------------------------------------------------------------- 1 | # 26. ES6 함수의 추가 기능 2 | ## 26.1 함수의 구분 3 | ```javascript= 4 | var foo = function() { 5 | return 1; 6 | } 7 | 8 | // 1. 일반적인 함수로서 호출 9 | foo() // 1 10 | 11 | // 2. 생성자 함수로서 호출 12 | new foo(); 13 | 14 | // 3. 메서드로서 호출 15 | var obj = {foo : foo}; 16 | obj.foo(); 17 | ``` 18 | 19 | es6이전의 함수는 사용 목적에 따라 명확히 구분되지 않고 일반 함수로서 호출할 수 있는 것은 물론 생성자 함수로서 호출 할 수 있음 20 | -> 모든 함수는 callable이면서 constuctor 21 | 22 | 이로 인해 생성자 함수로 호출되지 않아도 프로토타입을 생성하는 등 혼란을 주기 때문에 ES6에서는 함수를 다음과 같이 구분 23 | 24 | | es6 함수의 구분 | constructor | prototype | super | arguments | 25 | |-----|------|-----|-----|-----| 26 | |일반 함수 |✅|✅|❌ |✅| 27 | |메서드 |❌|❌ |✅|✅| 28 | |화살표 함수 |❌ |❌ |❌ |❌ | 29 | 30 | ## 26.2 메서드 31 | ES6 사양에서의 메서드 32 | - 메서드 축약 표현으로 정의된 함수로 인스턴스를 생성할 수 없는 non-constructor 33 | - 인스턴스를 생성할 수 없으므로 prototype 프로퍼티가 없고 생성하지도 않음. 34 | - 자신을 바인딩한 객체를 가리키는 내부 슬롯 HomeObject를 가짐. 35 | ES6 메서드가 아닌 함수는 super를 사용할 수 없음 (내부 슬롯 HomeObject를 갖지 않기 때문에) 36 | 37 | ## 26.3 화살표 함수 38 | ### 26.3.1 화살표 함수 정의 39 | #### 함수 정의 40 | 함수 선언문으로 정의 ❌ 함수 표현식으로 정의 :heavy_check_mark: 41 | 42 | #### 매개변수 선언 43 | 매개변수가 여러개인 경우 소괄호()안에 매개변수를 선언 44 | 45 | 한개인 경우에만 소괄호를 생략할 수 있음 46 | 47 | #### 함수 몸체 정의 48 | - 함수 몸체가 하나의 문으로 구성된다면 중괄호 생략 가능 49 | - 생략한 경우, 표현식이 아닌 문이라면 반환이 불가능 하기 때문에 에러가 발생한다. 50 | - 객체 리터럴을 반환하는 경우 소괄호로 감싸주어야 함. 51 | - 즉시실행함수로 사용 가능 52 | - 일급 객체이므로 고차함수에 인수로 전달 가능 53 | 54 | ### 26.3.2 화살표 함수와 일반 함수의 차이 55 | 1. 화살표 함수는 인스턴스를 생성할 수 없는 non-contructor 56 | 2. 중복된 매개변수 이름 선언 ❌ 57 | 3. 화살표 함수는 함수 자체의 this, arguments, super, new.target 바인딩을 갖지 않음 58 | 화살표 함수 내부에서 위 키워드를 참조하는 경우 스코프체인을 통해 상위 스코프의 키워드를 참조함. 59 | 60 | ### 26.3.3 this 61 | 콜백함수의 this와 외부 함수의 this는 서로 다른 값을 가짐. 이 문제를 해결하기 위해 62 | 1. 외부 함수의 this를 변수에 할당해 할당된 this를 적용 63 | 2. 고차함수의 두번째 인수로 외부함수의 this를 전달 64 | 3. Function.prototype.bind 메서드를 사용해 this를 바인딩 65 | 66 | **화살표 함수는 함수 자체의 this 바인딩을 갖지 않고 상위 스코프의 this를 그대로 참조 == lexical this** 67 | 68 | 화살표 함수는 자체 this 바인딩을 갖지 않기 때문에 call, apply, bind 메서드를 사용해도 화살표 함수 내부의 this를 교체할 수 없음 69 | 70 | ### 26.3.4 super 71 | this와 마찬가지로 상위 스코프의 super를 참조 72 | 73 | ### 26.3.5 arguments 74 | 상위 스코프의 arguments를 참조 75 | 화살표 함수로 가변 인자 함수를 구현해야할 때는 반드시 rest 파라미터를 사용 76 | 77 | ## 26.4 Rest 파라미터 78 | ### 26.4.1 기본 문법 79 | 앞에 점 세개를 붙여 정의한 매개변수 80 | 함수에 전달된 인수들의 목록을 배열로 받음 81 | - 반드시 마지막 파라미터이어야 하며, 한 개만 선언할 수 있음 82 | - 함수 객체의 length 프로퍼티에 영향을 주지 않음 83 | 84 | ### 26.4.2 Rest 파라미터와 arguments 객체 85 | 기존엔 매개변수의 갯수를 확정할 수 없는 경우, arguments 객체를 활용하여 인수를 전달받음 86 | 87 | arguments 객체는 유사 배열 객체로 배열 메서드를 사용하기 위해선 apply 메서드를 사용해 객체를 배열에 바인딩 시켜주는 작업이 필요했음. 88 | 89 | ES6에서는 Rest파라미터를 이용해 객체를 모두 사용 90 | 91 | ## 26.5 매개변수 기본값 92 | 매개 변수 기본 값을 사용해 인수 체크 및 초기화 간소화가 가능 93 | (매개변수에 인수를 전달하지 않은 경우와 undefined를 전달한 경우) -------------------------------------------------------------------------------- /14) 26. 함수의 추가 기능/June.md: -------------------------------------------------------------------------------- 1 | # 26. ES6 함수의 추가 기능 2 | 3 | # 26.1 함수의 구분 4 | 5 | > ES6 이전의 모든 함수는 일반 함수로서 호출할 수 있는 것은 물론 생성자 함수로서 호출할 수 있다. ES6에서는 목적에 따라 함수를 세 가지 종류로 명확히 구분했다. 6 | 7 | - 일반함수 8 | - 메서드 9 | - 화살표 함수 10 | 11 | ## 메서드 12 | 13 | > ES6 사양에서 메서드는 메서드 축약 표현으로 정의된 함수만을 의미한다. 14 | 15 | ```javascript 16 | const obj = { 17 | x: 1, 18 | foo() { return this.x }; 19 | bar: function() { 20 | return this.x; 21 | } 22 | } 23 | ``` 24 | 25 | 위에서 bar는 그냥 일반 함수고 foo는 메서드다. 26 | 27 | ES6 사양에서 정의한 메서드는 인스턴스를 생성할수 없는 Non-constructor다. 따라서 ES6 메서드는 생성자 함수로서 호출할 수 없다. 28 | 29 | 본연의 기능 super를 추가하고, 의미적으로 맞지 않은 constructor 기능은 제거했기 때문에 30 | **메서드를 정의할 때 프로퍼티 값으로 익명 함수 표현식을 할당하는 ES6 이전의 방식은 사용하지 않는 것이 좋다.** 31 | 32 | ## 화살표 함수 33 | 34 | > 화살표 함수는 표현만 간략한 것이 아니라 내부 동작도 기존의 함수보다 간략하다. 35 | 36 | 화살표 함수와 일반 함수의 차이는 아래와 같다. 37 | 38 | 1. 화살표 함수는 인스턴스를 생성할 수 없다. non-constructor이다, new 연산자를 통해서 인스턴스를 생성하지 못한다는 것. 39 | 2. 화살표 함수는 인스턴스를 생성할 수 없으니 Prototype 프로퍼티가 없고, 프로토타입도 생성하지 않는다. 40 | 3. 중복된 매개변수 이름을 선언할 수 없다. (일반함수는 가능, 단 strict mode에선 안됨) 41 | 4. 화살표 함수는 함수 자체의 this, arguments, super, new target 바인딩을 갖지 않는다. 42 | - 만약 화살표 함수에서 위의 키워드들을 참조하려고 하면 상위 스코프 체인에서 찾는다. 43 | 44 | ## 화삻표 함수와 일반 함수의 가장 큰 차이는 This다. 45 | 46 | > 다시 기억하자. this는 호출할 때 결정한다. 47 | 48 | - 화살표 함수는 상위 스코프의 this를 가리킨다. 49 | - 화살표 함수는 함수 자체의 this 바인딩을 가지지 않는다. 그래서 화살표 함수 내부에서 This를 참조하면 상위 스코프의 this를 그대로 참조한다. 이것을 Lexical this라고 한다. 50 | - 화살표 함수에서 this를 참조하면 상위 스코프중에서 화살표 함수가 아닌 함수의 this를 참조하게 되어있다. 51 | - 화살표 함수는 함수 자체의 this 바인딩이 없어서 bind, call, apply 메서드가 먹히지 않는다. 52 | - 메서드를 화살표 함수로 정의하는 것은 피하자. this가 어디로 튈지 모른다. 53 | 54 | ```javascript 55 | // 메서드의 좋은 예 56 | const person = { 57 | name: "Lee", 58 | sayHi() { 59 | console.log("Hi"); 60 | }, 61 | }; 62 | ``` 63 | 64 | ## super 65 | 66 | > 화살표 함수는 함수 자체의 super를 갖지 않는다. 따라서 this와 마찬가지로 상위 스코프의 super를 참조한다. 67 | 68 | ## arguments 69 | 70 | > 화살표 함수는 함수 자체의 arguments 바인딩을 갖지 않는다. 또 상위 스코프의 arguments를 참조한다. 71 | 72 | 만약 화살표 함수에서 arguments를 받아와서 가변 인수에 대한 대처를 하고 싶으면 Rest 파라미터를 사용해야한다. 73 | 74 | # Rest 파라미터 75 | 76 | > 나머지 매개변수 라는 의미로 사용할 수 있고 ... 키워드를 통해서 사용할 수 있다. 77 | 78 | - Rest 파라미터는 함수 파라미터 마지막에 사용할 수 있다. (첫번째나 두번째,,, 이렇게 사용하면 에러남) 79 | - 화살표 함수에서 가변 인자 함수를 구현하고자 한다면 반드시 Rest 파리미터를 사용해야 한다. 80 | 81 | # 매개 변수의 기본 값 도입 82 | 83 | ```javascript 84 | function sum(x = 0, y = 0) { 85 | // 인수 체크 및 초기화를 간소화 할 수 있다. 86 | console.log(x, y); 87 | } 88 | 89 | sum(undefined, null); // 0 null 90 | ``` 91 | 92 | - undefined 를 전달한 경우에만 유효하다 93 | - Rest 파라미터는 기본 값을 지정할 수 없다. 94 | -------------------------------------------------------------------------------- /14) 26. 함수의 추가 기능/README.md: -------------------------------------------------------------------------------- 1 | # 26. 함수의 추가 기능 2 | 3 | ## 정리 4 | 5 | - [춘식]() 6 | - [뽀송 - 메인 발표자]() 7 | - [세인트]() 8 | - [이안]() 9 | - [준]() 10 | - [다나]() 11 | -------------------------------------------------------------------------------- /14) 26. 함수의 추가 기능/choonsik.md: -------------------------------------------------------------------------------- 1 | # 26. ES6 함수의 추가 기능 2 | 3 | ## 1. 함수의 구분 4 | 5 | ES6 이전의 모든 함수는 일반 함수로 호출(callable)할 수 있는 것은 물론 생성자 함수로도 호출(constructor)할 수 있다. 6 | 7 | | ES6 함수의 구분 | constructor | prototype | super | arguments | 8 | | --------------- | ----------- | --------- | ----- | --------- | 9 | | 일반 함수 | O | O | X | O | 10 | | 메서드 | X | X | O | O | 11 | | 화살표 함수 | X | X | X | X | 12 | 13 | ## 2. 메서드 14 | 15 | ES6 사양에서 메서드는 메서드 축약 표현으로 정의된 함수만을 의미한다. 16 | 17 | ```js 18 | const obj = { 19 | x: 1, 20 | // foo는 메서드이다. 21 | foo() { 22 | return this.x; 23 | }, 24 | // bar에 바인딩된 함수는 메서드가 아닌 일반 함수이다. 25 | bar: function () { 26 | return this.x; 27 | }, 28 | }; 29 | 30 | console.log(obj.foo()); // 1 31 | console.log(obj.bar()); // 1 32 | 33 | // obj.foo는 constructor가 아닌 ES6 메서드이므로 prototype 프로퍼티가 없다. 34 | obj.foo.hasOwnProperty("prototype"); // -> false 35 | 36 | // obj.bar는 constructor인 일반 함수이므로 prototype 프로퍼티가 있다. 37 | obj.bar.hasOwnProperty("prototype"); // -> true 38 | 39 | String.prototype.toUpperCase.prototype; // -> undefined 40 | String.fromCharCode.prototype; // -> undefined 41 | 42 | Number.prototype.toFixed.prototype; // -> undefined 43 | Number.isFinite.prototype; // -> undefined 44 | 45 | Array.prototype.map.prototype; // -> undefined 46 | Array.from.prototype; // -> undefined 47 | ``` 48 | 49 | ES6 메서드는 자신을 바인딩한 객체를 가리키는 내부 슬롯 [[HomeObject]]를 갖는다. 50 | 51 | ```js 52 | const base = { 53 | name: "Lee", 54 | sayHi() { 55 | return `Hi! ${this.name}`; 56 | }, 57 | }; 58 | 59 | // 1 60 | const derived = { 61 | __proto__: base, 62 | // sayHi는 ES6 메서드다. ES6 메서드는 [[HomeObject]]를 갖는다. 63 | // sayHi의 [[HomeObject]]는 sayHi가 바인딩된 객체인 derived를 가리키고 64 | // super는 sayHi의 [[HomeObject]]의 프로토타입인 base를 가리킨다. 65 | sayHi() { 66 | return `${super.sayHi()}. how are you doing?`; 67 | }, 68 | }; 69 | 70 | // 2 71 | const derived = { 72 | __proto__: base, 73 | // sayHi는 ES6 메서드가 아니다. 74 | // 따라서 sayHi는 [[HomeObject]]를 갖지 않으므로 super 키워드를 사용할 수 없다. 75 | sayHi: function () { 76 | // SyntaxError: 'super' keyword unexpected here 77 | return `${super.sayHi()}. how are you doing?`; 78 | }, 79 | }; 80 | 81 | console.log(derived.sayHi()); // Hi! Lee. how are you doing? 82 | ``` 83 | 84 | ## 3. 화살표 함수 85 | 86 | ### 화살표 함수 정의 87 | 88 | ```js 89 | const arrow = (x, y) => { ... }; 90 | 91 | const arrow = x => { ... }; 92 | 93 | const arrow = () => { ... }; 94 | 95 | // concise body 96 | const power = x => x ** 2; 97 | power(2); // -> 4 98 | 99 | // 위 표현은 다음과 동일하다. 100 | // block body 101 | const power = x => { return x ** 2; }; 102 | 103 | const arrow = () => const x = 1; // SyntaxError: Unexpected token 'const' 104 | 105 | // 위 표현은 다음과 같이 해석된다. 106 | const arrow = () => { return const x = 1; }; 107 | ``` 108 | 109 | 화살표 함수도 일급 객체이므로 Array.prototype.map, Array.prototype, filter, Array.prototype.reduce 같은 고차 함수에 인수로 전달할 수 있다. 110 | 111 | 화살표 함수는 콜백 함수로 정의할 때 유용하다. 112 | 113 | ### 화살표 함수와 일반 함수의 차이 114 | 115 | 1. 화살표 함수는 인스턴스를 생성할 수 없는 non-constructor다. 116 | 2. 중복된 매개변수 이름을 선언할 수 없다. 117 | 3. 화살표 함수는 함수 자체의 this, arguments, super, new.target 바인딩을 갖지 않는다. 118 | 119 | ### this 120 | 121 | 화살표 함수는 함수 자체의 this 바인딩을 갖지 않는다. 122 | 따라서 화살표 함수 내부에서 this를 참조하면 상위 스코프의 this를 그대로 참조한다. 123 | 이를 lexical this라 한다. 124 | 125 | 화살표 함수 자체의 this 바인딩은 존재하지 않고, 화살표 함수 내부에서 this를 참조하면 일반적인 식별자처럼 스코프 체인을 통해 상위 스코프에서 this를 탐색한다. 126 | 127 | 화살표 함수 자체의 this 바인딩이 없기 때문에 128 | Function.prototype.call, Function.prototype.apply, Function.prototype.bind 메서드를 사용해도 this를 교체할 수 없다. 129 | 130 | 일반 함수가 아닌 ES6 메서드를 동적 추가하고 싶다면 객체 리터럴을 바인딩하고 프로토타입의 constructor 프로퍼티와 생성자 함수 간의 연결을 재설정한다. 131 | 132 | ### super 133 | 134 | 함수 자체의 super 바인딩을 갖지 않는다. 135 | super를 참조하면 상위 스코프의 super를 참조한다. 136 | 137 | ### arguments 138 | 139 | 함수 자체의 arguments 바인딩을 갖지 않는다. 140 | auguments를 참조하면 상위 스코프의 arguments를 참조한다. 141 | 142 | ## 4. Rest 파라미터 143 | 144 | ### 기본 문법 145 | 146 | 함수에 전달된 인수들의 목록을 배열로 전달받는다. 147 | 148 | ```js 149 | function foo(...rest) { 150 | // 매개변수 rest는 인수들의 목록을 배열로 전달받는 Rest 파라미터다. 151 | console.log(rest); // [ 1, 2, 3, 4, 5 ] 152 | } 153 | 154 | foo(1, 2, 3, 4, 5); 155 | ``` 156 | 157 | rest파라미터는 반드시 마지막 파라미터야 한다. 158 | Rest 파라미터는 단 하나만 선언할 수 있고, 함수 객체의 length 프로퍼티에 영향을 주지 않는다. 159 | 160 | ### Rest 파라미터와 arguments 객체 161 | 162 | arguments 객체는 함수 호출 시 전달된 인수들의 정보를 담고 있는 순회 가능한 유사 배열 객체이며 함수 내부에서 지역 변수처럼 사용할 수 있다. 163 | 164 | Rest 파라미터를 사용하면 유사 배열 객체인 arguments를 배열로 변환해야 하는 번거로움을 피할 수 있다. 165 | 166 | 화살표 함수로 가변 인자 함수를 구현해야 할 때는 반드시 Rest 파라미터를 사용해야 한다. 167 | 168 | ## 5. 매개변수 기본값 169 | 170 | 인수가 전달되지 않은 매개변수의 값은 undefined다. 171 | ES6에서 도입된 매개변수 기본값을 사용하면 함수 내에서 수행하던 인수 체크 및 초기화를 간소화할 수 있다. 172 | 173 | ```js 174 | function sum(x = 0, y = 0) { 175 | return x + y; 176 | } 177 | 178 | console.log(sum(1, 2)); // 3 179 | console.log(sum(1)); // 1 180 | ``` 181 | 182 | Rest 파라미터에는 기본값을 지정할 수 없다. 183 | 184 | 매개변수 기본값은 함수 정의 시 선언한 매개변수 개수를 나타내는 함수 객체의 length 프로퍼티와 arguments 객체에 아무 영향을 주지 않는다. 185 | -------------------------------------------------------------------------------- /15) 27. 배열/June.md: -------------------------------------------------------------------------------- 1 | # 배열 2 | 3 | # 27.2 자바스크립트 배열은 배열이 아니다. 4 | 5 | 장단점 6 | 7 | - 일반적인 배열은 인덱스로 요소에 빠르게 접근할 수 있다. 하지만 특정 요소를 검색하거나 요소를 삽입 또는 삭제하는 경우에는 효율적이지 않다. 8 | 9 | - 자바스크립트 배열은 해시 테이블로 구현된 객체이므로 인덱스로 요소에 접근하는 경우 일반적인 배열보다 성능적인 면에서 느릴 수 밖에 없는 구조적인 단점이 있다. 하지만 특정 요소를 검색, 삽입, 삭제 같은 경우에는 일반적인 경우보다 빠를 수도 있다. 10 | 11 | # 27.3 length와 희소 배열 12 | 13 | - empty는 실제로 추가된 배열의 요소가 아니다. 14 | 15 | - 희소배열이라는 건 배열의 요소가 연속적으로 존재하지 않고 일부가 비어 있는 배열을 희소 배열이라고 한다. 16 | 17 | # 27.4 배열 생성 18 | 19 | - 희소 배열의 원소를 출력하면 undefined가 뜬다. 20 | 21 | ### [] 22 | 23 | ### new Array() 24 | 25 | ### Array.of 26 | 27 | > 인수들을 요소로 갖는 배열 생성 28 | 29 | ```javascript 30 | Array.of(1); // [1] 31 | 32 | Array.of(1, 2, 3); // [1, 2, 3] 33 | 34 | Arrray.of("string"); // ['string'] 35 | ``` 36 | 37 | ### Array.from 38 | 39 | # 27.5 배열 요소의 참조 40 | 41 | - 존재하지 않는 요소를 참조하면 `undefined`가 반환된다. 42 | 43 | # 27.6 배열 요소의 추가와 갱신 44 | 45 | - length 프로퍼티 값보다 큰 인덱스로 새로운 요소를 추가하면 희소 배열이 된다. 46 | 47 | ```javascript 48 | const arr = [0]; 49 | 50 | arr[100] = 100; 51 | 52 | console.log(arr); // [0, empty x 98, 100]; 53 | ``` 54 | 55 | # 27.7 배열 요소의 삭제 56 | 57 | > 배열은 사실 객체라서 delete 연산자를 사용할 수 있다. 58 | 59 | - delete 인덱스로 배열의 요소를 삭제하면 희소 배열이 된다. 60 | - length에는 변화가 없다. 그래서 되도록이면 사용하지 말자. 61 | 62 | # 27.8 배열 메서드 63 | 64 | ### Array.isArray 65 | 66 | > 전달된 인수가 배열이면 true, 아니면 false 67 | 68 | ### Array.prototype.indexOf 69 | 70 | > 원본 배열에서 인수로 전달된 요소를 검색해서 인덱스를 반환한다. 71 | 72 | - 배열에 없으면 -1을 반환 73 | - indexOf보다 ES7의 includes를 사용하면 가독성이 더 좋다. 74 | 75 | ### Array.prototype.concat 76 | 77 | > 인수로 전달된 값들을 원본 배열의 마지막 요소로 추가한 배열을 반환하는 메서드 78 | 79 | - push, unshift와는 다르게 배열을 반환하고, 원본 배열을 변환시키지 않는다. 80 | - `push`, `unshift`, `concat` 메서드들 보다는 스프레드 문법을 일관성 있게 사용하자. 81 | 82 | ### Array.prototype.splice 83 | 84 | > splice(시작 인덱스, 삭제할 요소의 개수, ...제거한 위치에 삽입할 요소 목록들); 85 | 86 | - 반환값은 제거된 요소들의 목록이 반환값으로 나온다. 87 | - 원본 배열을 바꾼다. 88 | 89 | ### Array.prototype.flat 90 | 91 | > 인수로 전달한 깊이만큼 재귀적으로 배열을 평탄화한다. 92 | 93 | # 27.9 배열 고차 함수 94 | 95 | > 고차 함수는 함수를 인수로 전달받거나 함수를 반환하는 함수를 말한다. 96 | > 자바스크립트의 함수는 일급 객체이므로 함수를 값처럼 인수로 전달하고, 반환할 수도 있다. 고차 함수는 외부 상태의 변경이나 가변 데이터를 피하고 불변성을 지향하는 함수형 프로그래밍에 기반을 두고 있다. 97 | 98 | > 순수 함수를 통해 부수 효과를 최대한 억제하여 오류를 피하고 프로그램의 안정성을 높일 수 있다. 99 | 100 | ### Array.prototype.forEach 101 | 102 | - for문과 달리 break, continue 문을 사용할 수 없다. 103 | - 희소 배열의 경우 존재하지 않는 요소는 순회 대상에서 제외된다. 104 | - map, filter, reduce 전부 마찬가지다. 105 | - for문에 비해서 성능이 좋진 않지만, 가독성이 더 좋으므로 요소가 대단히 많은 배열을 순회하거나 시간이 많이 걸리는 복잡한 코드 또는 높은 성능이 필요한 경우가 아니면 for문 대신 forEach를 사용하자. 106 | 107 | ### Array.prototype.map 108 | 109 | ### Array.prototype.filter 110 | 111 | > 콜백 함수의 반환값이 true인 요소로만 구성된 새로운 배열을 반환한다. 112 | 113 | - filter는 요소가 같으면 전부 삭제되므로 하나만 삭제하고 싶다면 `indexOf` 메서드를 통해 인덱스를 취득하고, `splice` 메서드를 사용하자. 114 | 115 | ### Array.prototype.reduce 116 | 117 | > 자신을 호출한 배열을 모든 요소를 순회하며 인수로 전달받은 콜백 함수를 반복 호출한다. 그리고 콜백 함수의 반환값을 다음 순회시 콜백 함수의 첫 번째 인수로 전달하면서 계쏙 콜백 함수를 호출하면서 하나의 결과값을 만들어서 반환한다. 118 | 119 | reduce는 아래와 같은 상황에서 쓰일 수 있다. 120 | 121 | - 평균 구하기 122 | - 최대값 구하기 123 | - 요소 중복 횟수 구하기 124 | - 중첩 배열 평탄화 125 | - 중복 요소 제거 (filter가 더 직관적) 126 | 127 | reduce를 사용할 때는 초기값을 잘 넘겨주자. 128 | 129 | ### Array.prototype.some 130 | 131 | > 배열의 요소를 순회하면서 전달된 콜백 함수에 반환값이 한 번이라도 true면 true, 아니면 false를 반환한다. 빈 배열이면 false를 반환한다. 132 | 133 | ### Array.prototype.every 134 | 135 | > some과 다르게 전부 만족해야 true를 반환한다. 136 | -------------------------------------------------------------------------------- /15) 27. 배열/README.md: -------------------------------------------------------------------------------- 1 | # 27. 배열 2 | 3 | ## 정리 4 | 5 | - [춘식]() 6 | - [뽀송]() 7 | - [세인트 - 메인 발표자]() 8 | - [이안]() 9 | - [준]() 10 | - [다나]() 11 | -------------------------------------------------------------------------------- /15) 27. 배열/choonsik.md: -------------------------------------------------------------------------------- 1 | # 배열 2 | 3 | ## 배열이란 4 | 5 | 여러 개의 값을 순차적으로 나열한 자료구조 6 | 7 | 요소 : 배열이 가지고 있는 값 8 | 인덱스 : 요소에 접근할 정수 9 | length 프로퍼티 : 요소의 개수. 배열의 길이 10 | 11 | 생성 방식 : 배열 리터럴, Array 생성자 함수, Array.of, Array.from 메서드 12 | 13 | | 구분 | 객체 | 배열 | 14 | | - | - | - | 15 | | 구조 | 프로퍼티 키와 프로퍼티 값 | 인덱스와 요소 | 16 | | 값의 참조 | 프로퍼티 키 | 인덱스 | 17 | | 값의 순서 | X | O | 18 | | length 프로퍼티 | X | O | 19 | 20 | ## 자바스크립트 배열은 배열이 아니다 21 | 22 | 희소 배열 : 배열의 요소가 연속적으로 이어져 있지 않은 배열 23 | 자바스크립트의 배열은 일반적인 배열의 동작을 흉내 낸 특수한 객체다. 24 | 25 | 자바스크립트 배열은 인덱스를 나타내는 문자열을 프로퍼티 키로 가지며 length 프로퍼티를 갖는다. 26 | 자바스크립트 배열의 요소는 사실 프로퍼티 값이다. 27 | 28 | - 일반적인 배열은 인덱스로 요소에 빠르게 접근 가능하나 요소를 삽입 삭제하는 경우 효율적이지 않다. 29 | - 자바스크립트 배열은 해시 테이블로 구현된 객체로, 인덱스로 요소에 접근하는 경우 일반적인 배열보다 성능에서 느리다. 하지만 요소의 삽입 삭제가 일반적인 배열보다 빠르다. 30 | 31 | ## length 프로퍼티와 희소 배열 32 | 33 | length 프로퍼티 값을 할당하면 그 크기 만큼 배열의 길이가 줄어들 수 있다. 늘어날 수는 없다. 34 | 자바스크립트는 희소 배열을 문법적으로 허용한다. 35 | 36 | 희소 배열은 length와 배열 요소의 개수가 일치하지 않는다. 37 | 희소 배열의 length는 희소 배열의 실제 요소 개수보다 언제나 크다. 38 | 39 | 배열에는 같은 타입의 요소를 연속적으로 위치시키는 것이 최선이다. 40 | 41 | ## 배열 생성 42 | 43 | ### 배열 리터럴 44 | 45 | 가장 간편한 방식 46 | 47 | ```js 48 | const arr= [1, , 3]; 49 | ``` 50 | 51 | ### Array 생성자 함수 52 | 53 | ```js 54 | const arr = new Array(10); // 희소 배열 55 | const arr = new Array(); // [] 56 | const arr = new Array(1, 2, 3); // [1, 2, 3] 57 | const arr = new Array({}); // [{}] 58 | ``` 59 | 60 | - 전달 인수는 0 ~ 4,294,967,295 61 | 62 | ### Array.of 63 | 64 | ```js 65 | Array.of(1); // [1] 66 | Array.of(1, 2, 3); // [1, 2, 3] 67 | Array.of('string'); // ['string'] 68 | ``` 69 | 70 | ### Array.from 71 | 72 | 유사 배열 객체, 이터러블 객체를 인수로 전달받아 배열로 변환하여 반환한다. 73 | 74 | ```js 75 | Array.from({length: 2, 0: 'a', 1: 'b'}); // ['a', 'b'] 76 | Array.from('Hello'); // ['H', 'e', 'l', 'l', 'o'] 77 | Array.from({ length: 3 }); // [undefined, undefined, undefined] 78 | Array.from({ length: 3 }, (_, i) => i); // [0, 1, 2] 79 | ``` 80 | 81 | ## 배열 요소의 참조 82 | 83 | 대괄호 표기법. 인덱스를 사용한다. 84 | 존재하지 않은 요소 접근은 undefined 반환 85 | 86 | ## 배열 요소의 추가와 갱신 87 | 88 | 존재하지 않는 인덱스를 사용해 값을 할당하면 새로운 요소가 추가된다. 89 | 이미 존재하는 인덱스를 사용해 값을 할당하면 요소 값이 갱신된다. 90 | 정수 이외의 값을 인덱스처럼 사용하면 프로퍼티가 생성되며 length에 영향을 주지 않는다. 91 | 92 | ## 배열 요소의 삭제 93 | 94 | ```js 95 | delete arr[1]; 96 | ``` 97 | 98 | ```js 99 | arr.splice(삭제 시작할 인덱스, 삭제할 요소 수); // 권장 100 | ``` 101 | 102 | ## 배열 메서드 103 | 104 | Array 생성자 함수는 정적 메서드를, 105 | Array.prototype은 프로토타입 메서드를 제공한다. 106 | 107 | 배열에는 원본 배열을 직접 변경하는 메서드와 새로운 배열을 생성해 반환하는 메서드가 있다. 108 | 가급적이면 원본 배열을 직접 변경하지 않는 메서드를 사용하는 편이 좋다. 109 | 110 | ### Array.isArray 111 | 112 | 전달된 인수가 배열이면 true, 아니면 false 113 | 114 | ### Array.prototype.indexOf 115 | 116 | 특정 요소가 존재하는지 확인 117 | 권장 : Array.prototype.includes() 118 | 119 | ### Array.prototype.push 120 | 121 | 원본 배열을 변경 122 | 권장 : arr[arr.length] = value; 123 | 권장 : const newArr = [...arr, 3]; 124 | 125 | ### Array.prototype.pop 126 | 127 | 원본 배열을 변경 128 | 비어있으면 undefined 129 | 130 | ### Array.prototype.unshift 131 | 132 | 전달 인수를 모두 원본 배열의 선두에 추가하고 length 반환 133 | 134 | ### Array.prototype.shift 135 | 136 | 원본 배열 변경 137 | 첫 번째 요소를 제거하고 그 요소를 반환 138 | 139 | ### Array.prototype.concat 140 | 141 | 전달 인수를 원본 배열의 마지막 요소로 추가한 새로운 배열을 반환 142 | 권장 : 스프레드 문법으로 대체할 수 있다. 143 | 144 | ### Array.prototype.splice(start, deleteCount, items) 145 | 146 | 원본 배열 변경 147 | 148 | ### Array.prototype.slice(start, end) 149 | 150 | 새로운 배열 반환 151 | 152 | ### Array.prototype.join 153 | 154 | 전달 인수를 구분자로 연결한 문자열을 반환한다. 155 | 156 | ### Array.prototype.reverse 157 | 158 | 원본 배열을 변경 159 | 160 | ### Array.prototype.fill(item, startIndx, endIndex) 161 | 162 | 원본 배열을 변경 163 | 164 | ### Array.prototype.includes(item, startIndex) 165 | 166 | 특정 요소 포함 여부 167 | 168 | ### Array.prototype.flat(depth) 169 | 170 | 배열 평탄화 171 | 172 | ## 배열 고차 함수 173 | 174 | 고차 함수 : 함수를 인수로 전달받거나 함수를 반환하는 함수. 불변성을 지향하는 함수형 프로그래밍 기반 175 | 함수형 프로그래밍 : 순수 함수와 보조 함수의 조합을 통해 로직 내에 존재하는 조건문과 반복문을 제거하여 복잡성을 해결하고 변수의 사용을 억제해 상태 변경을 피하려는 프로그래밍 패러다임. 순수 함수를 통해 부수 효과를 최대한 억제해 프로그램의 안정성을 높인다. 176 | 177 | ### Array.prototype.sort(비교 함수) 178 | 179 | 배열의 요소 정렬 180 | 숫자 타입도 일시적으로 문자열로 변환해 정렬한다. 181 | 182 | quicksort 알고리즘에서 timsort 알고리즘으로 바뀌었다. 183 | 184 | ### Array.prototype.forEach 185 | 186 | for문을 대체 187 | 반환값은 언제나 undefined. this도 undefined (strict mode) 188 | break, continue문을 사용할 수 없다. 189 | for문에 비해 성능은 떨어지나 가독성은 더 좋다. 190 | 191 | ### Array.prototype.map 192 | 193 | 콜백 함수의 반환값들로 구성된 새로운 배열을 반환한다. 194 | 195 | ### Array.prototype.filter(item, index, arr) 196 | 197 | 콜백 함수의 반환값이 true인 요소로만 구성된 새로운 배열을 반환한다. 198 | 199 | ### Array.prototype.reduce(accumulator, currentValue, index, array) 200 | 201 | 인수로 전달된 콜백 함수를 반복 호출해 하나의 결과값을 반환한다. 202 | 203 | ```js 204 | const average = values.reduce((acc, cur, i, {length}) => { 205 | return i === length - 1? (acc + cur) / length : acc + cur; 206 | }, 0) 207 | 208 | const max = values.reduce((acc, cur) => (acc > cur ? acc : cur), 0) 209 | 210 | const count = fruits.recude((acc, cur) => { 211 | acc[cur] = (acc[cur] || 0) + 1; 212 | return acc; 213 | }, {}) 214 | 215 | const flatten = values.reduce((acc, cur) => acc.concat(cur), []) 216 | 217 | const uniques = values.reduce((unique, val, i, _values) => 218 | _values.indexOf(val) === i ? [...unique, val] : unique, [] 219 | ) 220 | ``` 221 | 222 | ### Array.prototype.some 223 | 224 | 콜백 함수에 대해 단 하나라도 참이면 true 225 | 226 | ### Array.prototype.every 227 | 228 | 콜백 함수에 대해 모두 참이면 true 229 | 230 | ### Array.prototype.find 231 | 232 | 콜백 함수의 반환값이 true인 첫번째 요소 or undefined 233 | 234 | ### Array.prototype.findIndex 235 | 236 | 콜백 함수를 호출해 반환값이 true인 첫번째 요소의 인덱스 or -1 237 | 238 | ### Array.prototype.flatMap 239 | 240 | map, flat 메서드를 순차적으로 실행하는 효과 -------------------------------------------------------------------------------- /16) 28. Number & 29. Math & 30. Date & 31. RegExp/June.md: -------------------------------------------------------------------------------- 1 | # 28 Number 2 | 3 | ```javascript 4 | /* Number 프로퍼티 */ 5 | Number.MAX_VALUE; // 자바스크립트에서 표현할 수 있는 가장 큰 수 6 | Number.MIN_VALUE; // 자바스크립트에서 표현할 수 있는 가장 작은 수 7 | Number.MAX_SAFE_INTEGER; // 자바스크립트에서 안전하게 표현할 수 있는 가장 큰 정수값 8 | Number.MIN_SAFE_INTEGER; // 자바스크립트에서 안전하게 표현할 수 있는 가장 작은 정수값 9 | Number.POSITIVE_INFINITY; // 양의 무한대를 나타내는 Infinity와 같다. 10 | Number.NEGATIVE_INFINITY; // 음의 무한대를 나타내는 Infinity와 같다. 11 | Number.NaN; // window.NaN과 같다. 12 | 13 | /* Number 메서드 */ 14 | Number.isFinite(); // 무한수인지 유한수인지 판별, 유한수면 true 반환 15 | Number.isInteger(); // 정수면 true 반환 16 | Number.isNaN(); // 숫자값이 NaN이면 true 반환 17 | Number.isSafeInteger(); // 안전한 정수면 true, -(2^53 - 1), (2^53 - 1) 정수 값이다. 18 | Number.prototype.toExponential(); // 지수 표기법으로 변환하여 문자열로 반환 19 | Number.prototype.toFixed(); // 숫자를 반올림하여 문자열로 반환 20 | Number.prototype.toPrecision(); // 전체 자릿수까지 유효하도록 나머지 자릿수를 반올림하여 문자열로 반환 21 | Number.prototype.toString(); // 숫자를 문자열로 변환해서 반환한다. 22 | ``` 23 | 24 | # 29 Math 25 | 26 | > 수학적인 상수와 함수를 위한 프로퍼티와 메서드를 제공한다. Math는 생성자 함수가 아니라서 정적 프로퍼티와 정적 메서드만 제공한다. 27 | 28 | ```javascript 29 | /* Math 프로퍼티 */ 30 | Math.PI; // 3.1415926535... 31 | 32 | /* Math 메서드 */ 33 | Math.abs(); // 인수로 전달된 숫자의 절댓값을 반환한다. 34 | Math.round(); // 인수로 전달된 숫자의 소수점 이하를 반올림한 정수를 반환한다. 35 | Math.ceil(); // 인수로 전달된 숫자의 소수점 이하를 올림한 정수를 반환한다. 36 | Math.floor(); // 인수로 전달된 숫자의 소수점 이하를 내림한 정수를 반환한다. 37 | Math.sqrt(); // 인수로 전달된 숫자의 제곱근을 반환한다. 38 | Math.random(); // 0에서 1미만의 실수를 반환한다. 0은 포함, 1은 포함되지 않는다. 39 | Math.pow(); // 첫 번째 인수는 밑, 두 번째 인수는 지수로 거듭제곱한 결과를 반환한다. 지수연산자 ** 랑 같다. 40 | Math.max(); // 전달받은 인수 중에서 가장 큰 수를 반환한다. 41 | Math.min(); //전달받은 인수 중에서 가장 작은 수를 반환한다. 42 | ``` 43 | 44 | # 30 Date 45 | 46 | ```javascript 47 | Date.prototype.getDay(); // 요일을 나타내는 정수를 반환한다. 0부터 일요일 48 | Date.prototype.toDateString(); // Fri Jul 24 2020 이런식으로 반환 49 | Date.prototype.toTimeString(); // 12:300:00 GMT+0900 이런식으로 반환 50 | Date.prototype.toISOString(); // 2020-07-24T03:30:00.000Z 이런식으로 반환, slice(0, 10)하면 날짜만 받아올 수 있음 51 | ``` 52 | 53 | ### Date를 활요한 시계 예제 54 | 55 | ```javascript 56 | (function printNow() { 57 | const now = new Date(); 58 | 59 | const dayNames = [ 60 | "(일요일)", 61 | "(월요일)", 62 | "(화요일)", 63 | "(수요일)", 64 | "(목요일)", 65 | "(금요일)", 66 | "(토요일)", 67 | ]; 68 | 69 | const day = dayNames[now.getDay()]; 70 | const year = now.getFullYear(); 71 | const month = now.getMonth() + 1; 72 | const date = now.getDate(); 73 | let hour = now.getHours(); 74 | let minute = now.getMinutes(); 75 | let second = now.getSeconds(); 76 | const ampm = hour >= 12 ? "PM" : "AM"; 77 | 78 | // 12시간제로 변경 79 | hour %= 12; 80 | hour = hour || 12; // hour가 0이면 12로 변경 81 | 82 | // 10 미만인 분과 초를 2자리로 변경 83 | minute = minute < 10 ? "0" + minute : minute; 84 | second = second < 10 ? "0" + second : second; 85 | 86 | const nowText = `${year}년 ${month}월 ${date}일 ${day} ${hour}:${minute}:${second} ${ampm}`; 87 | 88 | console.log(nowText); 89 | 90 | setTimeout(printNow, 1000); 91 | })(); 92 | ``` 93 | 94 | # RegExp 95 | 96 | > 정규 표현식은 일정한 패턴을 가진 문자열의 집합을 표현하기 위해 사용하는 형식 언어다. 97 | 98 | - /regexp/i 형식으로 입력한다. regexp 양쪽에는 시작, 종료 기호가 들어가고, 끝에 i 자리에는 플래그가 들어간다. 99 | 100 | ```javascript 101 | /* RegExp 메서드 */ 102 | RedExp.prototype.exec; // 인수로 전달받은 문자열에 대해 정규 표현식의 패턴을 검색해서 매칭 결과를 배열로 반환 103 | RedExp.prototype.test; // 인수로 전달받은 문자열에 대해 정규 표현식의 패턴을 검색해서 매칭 결과를 불리언 값으로 반환한다. 104 | RedExp.prototype.match; // 대상 문자열과 인수로 전달받은 정규 표현식과의 매칭 결과를 배열로 반환 105 | ``` 106 | 107 | ### 플래그 108 | 109 | > 플래그는 정규 표현식의 검색 방식을 설정하기 위해 사용한다. 총 6개인데 중요한 3개를 살펴본다. 110 | 111 | - i (ignore case): 대소문자를 구별하지 않고 패턴을 검색 112 | - g (global): 대상 문자열 내에서 패턴과 일치하는 모든 문자열을 전역 검색 113 | - m (multi line): 문자열의 행이 바뀌더라도 패턴 검색을 계속한다. 114 | 115 | ### 패턴 116 | 117 | ```javascript 118 | const regExp = /.../g; // 임의의 3자리 문자열을 대소문자 구별하여 전역 검색 119 | const regExp = /A{1,2}/g; // A가 최소 1번, 최대 2번 반복되는 문자열 전역 검색 120 | ``` 121 | 122 | - `+`는 `{1,}`와 같다. 123 | - A+ 는 'A'가 최소 한번 이상 반복되는 문자열, 즉 A만으로 이루어진 문자열과 매치한다. 124 | - `?`는 최대 한 번 이상 반복되는 문자열, `?`는 `{0,1}`와 같다. 125 | - `|`는 `or`과 같다. /A|B/는 'A'또는 'B'를 의미한다. 126 | - `[]` 내에 `-`는 범위를 지정해준다. `[A-Z]` 대문자 알파벳을 검색한다. 127 | - `\d`는 숫자를 의미한다. 128 | - `[]` 안의 `^`은 `not`이다. 129 | - `[]` 밖의 `^`은 해당 문자열로 시작하는지 판단한다. 130 | - `$`은 문자열의 마지막을 의미한다. 131 | -------------------------------------------------------------------------------- /16) 28. Number & 29. Math & 30. Date & 31. RegExp/README.md: -------------------------------------------------------------------------------- 1 | # 28. Number & 29. Math & 30. Date & 31. RegExp 2 | 3 | ## 정리 4 | 5 | - [춘식]() 6 | - [뽀송]() 7 | - [세인트]() 8 | - [이안 - 메인 발표자]() 9 | - [준]() 10 | - [다나]() 11 | -------------------------------------------------------------------------------- /17) 32. String & 33. Symbol/JuneImage/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/17) 32. String & 33. Symbol/JuneImage/1.png -------------------------------------------------------------------------------- /17) 32. String & 33. Symbol/JuneImage/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/17) 32. String & 33. Symbol/JuneImage/2.png -------------------------------------------------------------------------------- /17) 32. String & 33. Symbol/JuneImage/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/17) 32. String & 33. Symbol/JuneImage/3.png -------------------------------------------------------------------------------- /17) 32. String & 33. Symbol/JuneImage/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PPO-F-MAN/modern-javascript-deep-dive/a628694cdcace6d1728ec33250c756992b1b4690/17) 32. String & 33. Symbol/JuneImage/4.png -------------------------------------------------------------------------------- /17) 32. String & 33. Symbol/README.md: -------------------------------------------------------------------------------- 1 | # 32. String & 33. Symbol 2 | 3 | ## 정리 4 | 5 | - [춘식]() 6 | - [뽀송]() 7 | - [세인트]() 8 | - [이안]() 9 | - [준 - 메인 발표자]() 10 | - [다나]() 11 | -------------------------------------------------------------------------------- /17) 32. String & 33. Symbol/choonsik.md: -------------------------------------------------------------------------------- 1 | # String 2 | 3 | ## String 생성자 함수 4 | 5 | ```js 6 | const strObj = new String(); 7 | console.log(strObj); // String {length: 0, [[PrimitiveValue]]: ""} 8 | 9 | const strObj = new String("Lee"); 10 | console.log(strObj); // String {0: "L", 1:"e", 2:"e", length: 3, [[PrimitiveValue]]: "Lee"} 11 | 12 | // 명시적 타입 변환 13 | String(1); // "1" 14 | String(NaN); // "NaN" 15 | ``` 16 | 17 | ## length 프로퍼티 18 | 19 | 문자열의 문자 개수를 반환한다. 20 | 21 | ## String 메서드 22 | 23 | 문자열은 변경 불가능한 원시 값이기 때문에 String 래퍼 객체도 읽기 전용 객체로 제공된다. (writable: false) 24 | 25 | ### String.prototype.indexOf 26 | 27 | 문자열을 검색해 첫 번째 인덱스를 반환 28 | 검색 실패하면 -1 반환 29 | 2번째 인수로 검색을 시작할 인덱스를 지정할 수 있다. 30 | 31 | ### String.prototype.search 32 | 33 | 인수로 전달받은 정규 표현식과 매치하는 문자열을 검색해 일치하는 문자열의 인덱스를 반환 34 | 검색 실패하면 -1 반환 35 | 36 | ### String.prototype.includes 37 | 38 | 인수 문자열이 포함되어 있는지 확인 : true, false 39 | 2번째 인수로 검색을 시작할 인덱스를 지정할 수 있다. 40 | 41 | ### String.prototype.startsWith 42 | 43 | 대상 문자열이 인수로 전달받은 문자열로 시작하는지 확인 : true, false 44 | 2번째 인수로 검색을 시작할 인덱스를 지정할 수 있다. 45 | 46 | ### String.prototype.endsWith 47 | 48 | 대상 문자열이 인수로 전달받은 문자열로 끝나는지 확인 : true, false 49 | 2번째 인수로 검색할 문자열의 길이 전달 50 | 51 | ### String.prototype.charAt 52 | 53 | 대상 문자열이 인수로 전달받은 인덱스에 위치한 문자를 검색하여 반환 54 | 범위를 벗어나면 빈 문자열 반환 55 | String.prototype.charCodeAt, String.prototype.codePointAt 56 | 57 | ### String.prototype.substring 58 | 59 | 첫 번째 인수 인덱스 문자 ~ 두 번째 인수 인덱스 문자 바로 이전 문자까지 반환 60 | 61 | ### String.prototype.slice 62 | 63 | String.prototype.substring과 동일하지만 음수 인수를 전달할 수 있다. 64 | 65 | ### String.prototype.toUpperCase 66 | 67 | 대문자 문자열 반환 68 | 69 | ### String.prototype.toLowerCase 70 | 71 | 소문자 문자열 반환 72 | 73 | ### String.prototype.trim 74 | 75 | 앞뒤 공백 문자 제거한 문자열 반환 76 | String.prototype.trimStart, String.prototype.trimEnd 77 | 78 | ### String.prototype.repeat 79 | 80 | 대상 문자열을 인수만큼 반복 81 | 82 | ### String.prototype.replace 83 | 84 | 첫 번째 인수로 전달받은 문자열, 정규표현식을 검색해 두 번째 인수로 치환한 문자열을 반환 85 | ```js 86 | const str = 'Hello world'; 87 | str.replace('world', '$&') // $& => 검색된 문자열 88 | ``` 89 | 90 | ### String.prototype.split 91 | 92 | 첫 번째 인수 문자열 또는 정규 표현식을 검색해 문자열을 구분한 후 분리된 각 문자열로 이루어진 배열 반환 93 | 두 번째 인수로 배열의 길이 지정 94 | 95 | # Symbol 96 | 97 | ## 심벌이란? 98 | 99 | 변경 불가능한 원시 타입의 값 100 | 다른 값과 중복되지 않는 유일무이한 값이다. 101 | 유일한 프로퍼티 키를 만들기 위해 사용한다. 102 | 103 | ## 심벌 값의 생성 104 | 105 | Symbol 함수를 호출해 생성한다. 106 | 다른 값과 절대 중복되지 않는 유일무이한 값이며 외부로 노출되지 않아 확인할 수 없다. 107 | 108 | ### Symbol 함수 109 | 110 | ```js 111 | const mySymbol = Symbol(); 112 | new Symbol(); // TypeError: Symbol is not a constructor 113 | 114 | const mySymbol1 = Symbol('mySymbol'); 115 | const mySymbol2 = Symbol('mySymbol'); 116 | 117 | console.log(mySymbol1 === mySymbol2); // false 118 | 119 | const mySymbol = Symbol('mySymbol'); 120 | console.log(mySymbol.description); // mySymbol 121 | console.log(mySymbol.toString()); // Symbol(mySymbol) 122 | 123 | console.log(mySymbol + ''); // TypeError: Cannot convert a Symbol value to a string 124 | console.log(+mySymbol); // TypeError: Cannot convert a Symbol value to a string 125 | 126 | console.log(!!mySymbol); // true 127 | if (mySymbol) console.log('mySymbol is not empty'); 128 | ``` 129 | 130 | ### Symbol.for / Symbol.keyFor 메서드 131 | 132 | Symbol.for : 인수로 전달받은 문자열을 키로 사용해 키와 심벌 값의 쌍들이 저장되어 있는 전역 심벌 레지스트리에서 해당 키와 일치하는 심벌 값을 검색한다. 133 | - 검색에 성공하면 검색된 심벌 값 반환 134 | - 실패하면 새로운 심벌 값을 생성해 저장한 후 생성된 심벌 값 반환 135 | 136 | Symbol.keyFor : 전역 심벌 레지스트리에 저장된 심벌 값의 키를 추출할 수 있다. 137 | 138 | ```js 139 | const s1 = Symbol.for('mySymbol'); 140 | const s2 = Symbole.for('mySymbol'); 141 | 142 | console.log(s1 === s2); // true 143 | 144 | Symbol.keyFor(s1); // mySymbol 145 | ``` 146 | 147 | ### 심벌과 상수 148 | 149 | ```js 150 | // enum을 흉내내어 객체의 변경 방지 151 | const Direction = Object.freeze({ 152 | UP: Symbol('up'), 153 | DOWN: Symbol('down'), 154 | LEFT: Symbol('left'), 155 | RIGht: Symbol('right') 156 | }); 157 | 158 | const myDirection = Direction.UP; 159 | 160 | if (myDirection === Direction.UP) { 161 | console.log('You are going UP.'); 162 | } 163 | ``` 164 | 165 | ### 심벌과 프로퍼티 키 166 | 167 | 객체의 프로퍼티 키는 빈 문자열을 포함하는 모든 문자열 또는 심벌 값으로 만들 수 있으며 동적으로 생성할 수 있다. 168 | ```js 169 | const obj = { 170 | [Symbol.for('mySymbol')]: 1 171 | }; 172 | obj[Symbol.for('mySymbol')]; // 1 173 | ``` 174 | 175 | ### 심벌과 프로퍼티 은닉 176 | 177 | 심벌 값을 위처럼 프로퍼티로 생성하면 어느정도 은닉이 가능하다. 178 | 179 | ### 심벌과 표준 빌트인 객체 확장 180 | 181 | 표준 빌트인 객체는 중복을 방지해 읽기 전용으로 사용하는 것이 좋다. 182 | 심벌 값으로 표준 빌트인 객체를 확장하는 것이 좋다. 183 | 184 | ```js 185 | Array.prototype[Symbol.for('sum')] = function() { 186 | return this.reduce((acc, cur) => arr + cur, 0); 187 | }; 188 | 189 | [1, 2][Symbol.for('sum')](); // 3 190 | ``` 191 | 192 | ### Well-known Symbol 193 | 194 | 빌트인 심벌 값은 Symbol 함수의 프로퍼티에 할당되어 있다. 195 | 이를 Well-known Symbol이라 부르며 자바스크립트 엔진의 내부 알고리즘에 사용된다. 196 | 197 | 예를 들어 순회 가능한 빌트인 이터러블은 Well-known Symbol인 Symbol.iterator를 키로 갖는 메서드를 가지며, Symbol.iterator 메서드를 호출하면 이터레이터를 반환하도록 ECMAScript 사양에 규정되어 있다. 빌트인 이터러블은 이터레이션 프로토콜을 준수한다. 198 | 199 | ```js 200 | const iterable = { 201 | [Symbol.iterator]() { 202 | let cur = 1; 203 | const max = 5; 204 | return { 205 | next() { 206 | return { value: cur++, done: cur > max + 1 }; 207 | } 208 | }; 209 | } 210 | }; 211 | 212 | for (const num of iterable) { 213 | console.log(num); // 1 2 3 4 5 214 | } 215 | ``` -------------------------------------------------------------------------------- /17) 32. String & 33. Symbol/dana.md: -------------------------------------------------------------------------------- 1 | # 32. String 2 | ## 32.1 string 생성자 함수 3 | string 객체는 생성자 함수 객체 4 | new 연산자와 함께 호출해 string을 생성할 수 있음. 5 | 6 | 인수를 전달하지 않고, new 연산자와 함께 호출하면 StringData 내부 슬롯에 빈 문자열을 할당한 String 래퍼 객체를 생성 7 | ```javascript= 8 | const strObj = new String("test"); 9 | console.log(strObj); 10 | // String { length : 0, [[PrimitiveValue]] : ""} 11 | 12 | const strObj = new String(); 13 | console.log(strObj); 14 | // String { 0 : 't', 1: 'e', 2 : 's', 3 : 't' , length : 0, [[PrimitiveValue]] : "test"} 15 | ``` 16 | 17 | PrimitiveValue === StringData (접근할 수 없는 프로퍼티) 18 | length 프로퍼티와 인덱스를 나타내는 숫자 형식의 문자열을 프로퍼티 키로, 각 문자를 프로퍼티 값으로 갖는 유사 배열 객체이면서 이터러블 19 | 따라서 인덱스를 사용해 접근할 수는 있지만, 인덱스를 이용해 값을 변경할 수는 없음.(readonly) 20 | 21 | String에 인자로 문자열이 아닌 값을 넣으면 명시적으로 형 변환이 일어남. 22 | 23 | ## 32.2 length 프로퍼티 24 | 문자열의 문자 개수를 반환 하는 프로퍼티로, String 래퍼 객체는 배열과 마찬가지로 length 프로퍼티를 가짐. 25 | 1. 인덱스를 나타내는 숫자를 프로퍼티로 가짐 26 | 2. 각 문자를 프로퍼티 값으로 가짐 27 | => String 래퍼 객체는 유사 배열 객체 28 | 29 | ## 32.3 String 메서드 30 | 배열에는 두가지 메서드가 존재 31 | 1. 원본 배열을 직접 변경하는 메서드 32 | 2. 원본 배열을 직접 변경하지 않고 새로운 배열을 생성해 반환하는 메서드 33 | 34 | **String 래퍼 객체를 직접 변경하는 메서드가 아니라 새로운 메서드를 생성해 반납하는 것** 35 | 36 | ### String.prototype.indexOf 37 | > str.indexOf(검색할 값, [검색을 시작할 인덱스]) 38 | 39 | 대상 문자열에서 인수로 전달받은 문자열을 검색해 첫 번째 인덱스를 반환, 실패시 -1 반환 40 | 41 | 특정 문자열이 존재하는지 확인할 때 유용하며, `String.prototype.includes` 메서드를 활용하면 더 좋음 42 | 43 | ### String.prototype.search 44 | > str.search(정규표현식); 45 | 46 | 대상 문자열에서 인수로 전달받은 정규 표현식과 매치하는 문자열을 검색해 일치하는 문자열의 인덱스를 반환, 실패시 -1 반환 47 | 48 | ### 32.3.3 String.prototype.includes 49 | > str.includes(찾는 값, [검사를 시작할 인덱스]) 50 | 51 | 대상 문자열에 인수로 전달 받은 문자열이 포함되어 있는지 확인해 결과를 boolean 값으로 반환 52 | 53 | ### 32.3.4 String.prototype.startsWith 54 | > str.startsWith(찾는 값, [검색을 시작할 인덱스]) 55 | 56 | 대상 문자열이 인수로 전달받은 문자열로 시작하는지 확인해 그 결과를 boolean으로 반환 57 | 58 | ### 32.3.5 String.prototype.endsWith 59 | > str.endsWith(찾는 값, [검색을 시작할 인덱스]) 60 | 61 | 대상 문자열이 인수로 전달받은 문자열로 끝나는지 확인해 그 결과를 boolean으로 반환 62 | 63 | ### 32.3.6 String.prototype.charAt 64 | > str.charAt(인덱스 값) 65 | 66 | 대상 문자열에서 인수로 전달받은 인덱스에 위치한 문자를 검색해 반환 67 | 인덱스는 문자열의 범위(0 ~ 문자열길이-1) 사이의 정수 68 | 인덱스가 문자열의 범위를 벗어난 정수인 경우 빈 문자열을 반환 69 | 70 | 유사한 메서드로 charCodeAt, codePointAt 이 있음. 71 | 72 | ### 32.3.7 String.prototype.substring 73 | > str.substring(시작 문자 인덱스, [종료 문자 인덱스 + 1]) 74 | 75 | - 두번째 인자 생략시, 시작문자~마지막 인덱스까지 76 | - 첫번째 인수 > 두번째 인수 => 두 인수가 교환 77 | - 인수 < 0 || NaN => 0으로 취급 78 | - 인수 > 문자열의 길이 => 인수는 문자열의 길이로 취급 79 | 80 | indexOf 메서드와 함께 사용하면 특정 문자열을 기준으로 앞뒤에 위치한 부분 문자열을 취득 81 | 82 | ### 32.3.8 String.prototype.slice 83 | `substring` 메서드와 동일하게 동작하지만, 음수인 인수를 전달 할 수 있다는 점이 다름. 84 | 음수인 인자를 넣는 경우, 문자열의 가장 뒤에서부터 시작해 문자열을 잘라내 반환 85 | 86 | ### 32.3.9 String.prototype.toUpperCase 87 | 대상 문자열을 모두 대문자로 변경한 문자열을 반환 88 | 89 | ### 32.3.10 String.prototype.toLowerCase 90 | 대상 문자열을 모두 소문자로 변경한 문자열을 반환 91 | 92 | ### 32.3.11 String.prototype.trim 93 | 대상 문자열 앞뒤에 공백 문자가 있을 경우 이를 제거한 문자열을 반환 94 | 95 | `trimStart`나 `trimEnd`를 이용하면 앞 혹은 뒤의 공백만 제거 가능함 96 | 97 | ### 32.3.12 String.prototype.repeat 98 | > str.repeat(정수) 99 | 100 | 대상 문자열을 인수로 전달받은 정수만큼 반복해 연결한 새로운 문자열 반환 101 | 정수가 0이면 빈 문자열 반환, 음수면 RangeError 발생 102 | 인수 생략 시, 기본값 0이 설정 103 | 104 | ### 32.3.13 String.prototype.replace 105 | > str.replace(문자열/정규표현식, 대체할 문자열) 106 | - $&는 검색된 문자열을 의미 -> 해당 문자열에 다른 문자열을 추가하고 싶은 경우 사용 107 | 108 | 대상 문자열에서 첫번째 인수로 전달 받은 문자열 또는 정규표현식을 검색해 두번째 인수로 전달한 문자열로 치환한 문자열을 반환 109 | 110 | 두번째 인자로 치환 함수 전달 가능 111 | 112 | ### 32.3.14 String.prototype.split 113 | > str.split(문자열/정규표현식, [배열의 길이]) 114 | 115 | 대상 문자열에서 첫번째 인수로 전달한 문자열 또는 정규 표현식을 검색해 문자열을 구분한 후 분리된 각 문자열로 이루어진 배열을 반환 116 | 117 | 빈 문자열을 인수로 전달 시, 각 문자를 모두 분리하고, 빈 인수를 전달하면 문장 전체를 단일 요소로 하는 배열을 반환 118 | 119 | `reverse()`, `join()` 함수와 함께 문자열을 역순으로 뒤집을 수 있음. 120 | 121 | # 33. 7번째 데이터 타입 Symbol 122 | ## 33.1 심벌이란? 123 | ES6에서 도입된 7번째 데이터 타입으로 변경 불가능한 원시 타입의 값 124 | 다른 값과 중복되지 않는 유일무이한 값 125 | 이름 충돌 위험이 없는 유일한 프로퍼티 키를 만들기 위해 사용 126 | -> **하위 호환성을 보장하기 위해 도입** 127 | 128 | ## 33.2 심벌 값의 생성 129 | ### 33.2.1 Symbol 함수 130 | Symbol 함수를 호출해 생성 131 | 이 때 생성된 심볼 값은 외부로 노출되지 않아 확인할 수 없으며, 다른 값과 절대 중복되지 않는 유일무이한 값 132 | 133 | ```javascript= 134 | const mySymbol = Symbol() 135 | 136 | // 심볼 값은 외부로 노출되지 않아 확인할 수 없음 137 | console.log(mySymbol) // Symbol() 138 | ``` 139 | 140 | 다른 생성자 함수와 달리 new 연산자와 함께 호출하지 않음. 141 | 142 | 선택적으로 문자열을 인수로 전달 할 수 있으나. 심벌값에 대한 설명으로 디버깅 용도로 사용됨. 143 | -> 심벌 값에 대한 설명이 같더라도, 생성된 심볼은 유일무이한 값 144 | 145 | 심볼값도 객체처럼 접근시, 암묵적으로 래퍼 객체를 생성 146 | 147 | ```javascript= 148 | cosnt mySymbol = Symbol('mySymbol'); 149 | 150 | console.log(mySymbol.description) // mySymbol 151 | console.log(mySymbol.toString()) // Symbol(mySymbol) 152 | ``` 153 | 154 | 심볼은 암묵적으로 문자열이나 숫자 타입으로 변환되지 않음. 155 | 단, 불리언타입으로는 암묵적으로 변환 가능하다. -> 항상 true? 156 | 157 | ### 33.2.2 Symbol.for / Symbol.keyFor 메서드 158 | #### Symbol.for 메서드 159 | - 인수로 전달받은 문자열을 **키**로 사용해 키와 심볼 값의 쌍들이 저장되어 있는 전역 심볼 레지스트리에서 해당 키와 일치하는 심볼 값을 검색 160 | - 검색 성공 시, 새로운 심볼 값을 생성하지 않고 검색된 심볼 값을 반환 161 | - 검색 실패 시, 새로운 심볼 값을 생성해 Symbol.for 메서드의 인수로 전달된 키로 전역 심볼 레지스트리에 저장 후 생성된 심볼 값을 반환 162 | 163 | `Symbol.for` 메서드를 사용하면 애플리케이션 전역에서 중복되지 않는 유일무이한 상수인 심볼값을 단 하나만 생성해 전역 심볼 레지스트리를 통해 공유가 가능. 164 | 165 | #### Symbol.keyFor 메서드 166 | - 전역 심볼 레지스트리에 저장된 심볼 값의 키를 추출 167 | 168 | ## 33.3 심벌과 상수 169 | 예를 들어 방향을 나타내는 상수를 정의할 때, 170 | ```javascript= 171 | cosnt Direction = { 172 | UP : 1, 173 | DOWN : 2, 174 | ... 175 | } 176 | ``` 177 | 178 | **값에는 특별한 의미가 없고 상수 이름 자체에 의미가 있는 경우**, 변경/중복될 가능성이 있는 무의미한 상수 대신 중복될 가능성이 없는 유일무이한 심볼값 사용 가능 179 | 180 | ```javascript= 181 | cosnt Direction = { 182 | UP : Symbol('up'), 183 | DOWN : Symbol('down'), 184 | ... 185 | } 186 | ``` 187 | 188 | > ### enum 189 | > 명명된 숫자 상수의 집합으로 열거형이라고 부름 190 | > 자바스크립트에서는 enum을 사용하지 않지만, 타입스크립트에서는 enum을 지원 191 | > 자바스크립트에서 enum을 흉내내기 위해 Object.freeze 메서드와 심벌값 사용 192 | > ```javascript= 193 | >const Direction = Object.freeze({ 194 | > UP : Symbol('up'), 195 | > DOWN : Symbol('down'), 196 | > ... 197 | >}) 198 | >``` 199 | 200 | ## 33.4 심벌과 프로퍼티키 201 | 객체의 프로퍼티 키는 빈 문자열을 포함하는 모든 문자열 또는 심볼 값으로 생성 가능 (동적으로도 생성 가능) 202 | 203 | 심볼값으로 프로퍼티 키를 동적 생성해 프로퍼티를 만드는 방법 204 | ```javascript= 205 | const obj = { 206 | [Symbol.for('mySymbol')] : 1 207 | } 208 | ``` 209 | 210 | 심볼은 유일무이한 값이므로 심볼값으로 프로퍼티키를 만들면 다른 프로퍼티 키와 절대 충돌하지 않음 211 | 212 | ## 33.5 심볼과 프로퍼티 은닉 213 | 심볼값을 프로퍼티 키로 사용해 생성한 프로퍼티는 `for...in` 문이나 `Object.keys`, `Object.getOwnPropertyNames` 메서드로 검색 불가 214 | -> 외부에 노출할 필요 없는 프로퍼티 은닉 가능 215 | 216 | `Object.getOwnPropertySymbols` 메서드를 사용하면 심볼값을 키로 사용하는 프로퍼티 검색 가능 217 | 218 | ## 33.6 심벌과 표준 빌트인 객체(prototype) 확장 219 | 일반적으로 표준 빌트인 객체에 사용자 정의 메서드를 직접 추가해 확장하는 것은 권장하지 않음. 표준 빌트인 객체는 읽기 전용으로 사용하는 것을 권장 220 | 221 | > why? 222 | > 개발자가 직접 추가한 메서드와 미래에 표준 사양으로 추가될 메서드의 이름이 중복될 수 있기 때문 223 | > 중복될 가능성이 없는 심볼값으로 프로퍼티 키를 생성해 표준 빌트인 객체 확장시, 표준 빌트인 객체의 기존 프로퍼티와 충돌하지 않는 것은 물론, 어떤 프로퍼티 키와도 충돌할 위험이 없어 안전하게 표준 빌트인 객체 확장 가능 224 | 225 | ## 33.7 Well-known Symbol 226 | 자바스크립트가 기본 제공하는 빌트인 심볼 값 존재 -> 이를 well-known symbol 이라고 부름 227 | 228 | 만약 빌트인 이터러블이 아닌 일반 객체를 이터러블처럼 동작하도록 구현하고 싶다면, 이터레이션 프로토콜을 따르면 됨. 229 | - well-known symbol인 `Symbol.iterator`를 키로 갖는 메서드를 객체에 추가하고 이터레이터를 반환하도록 구현하면 그 객체는 이터러블이 됨. 230 | ```javascript= 231 | const iterable = { 232 | [Symbol.iterator]() { 233 | let cur = 1; 234 | const max = 5; 235 | 236 | return { 237 | next() { 238 | return { value : cur ++ , done : cur >max + 1 }; 239 | } 240 | } 241 | } 242 | } 243 | ``` 244 | -------------------------------------------------------------------------------- /18) 38. 브라우저의 렌더링 과정/June.md: -------------------------------------------------------------------------------- 1 | # 브라우저 동작 원리 2 | 3 | 1. 브라우저는 HTML, CSS, JavaScript, Image, Font... 등 렌더링에 필요한 리소스를 웹 서버에 요청하고 서버로부터 응답을 받습니다. 4 | 5 | 2. 받아온 HTML, CSS를 파싱해서 DOM, CSSOM을 생성하고 이들을 결합해서 Render Tree를 생성합니다. 6 | 7 | 3. 브라우저의 자바스크립트 엔진은 서버로부터 응답된 자바스크립트를 파싱하고 실행합니다. 이 때 자바스크립트는 DOM API를 통해서 DOM이나 CSSOM을 변경할 수 있습니다. 변경된 DOM과 CSSOM은 다시 렌더 트리로 결합됩니다. 8 | 9 | 4. 렌더 트리를 기반으로 HTML 요소의 위치와 크기를 계산하는 레이아웃과정을 거친다음 실제로 유저들에게 보여주기 위해서 그림을 그리는 페인트 과정을 수행합니다. 10 | 11 | --- 12 | 13 | # 조금 더 깊게 14 | 15 | ### 1. 네트워킹 과정 16 | 17 | 브라우저에 주소창에 요청을 보낼 주소를 입력하고 엔터를 입력하면 URL의 호스트 네임이 DNS를 통해서 IP주소로 변경되고 IP 주소를 갖는 서버를 찾아가서 요청을 전송합니다. 18 | 19 | - 이 때 요청하지 않은 img, CSS, JavaScript는 어떻게 가져오는 이유는 HTML을 파싱하는 도중에 외부 리소스를 로드하는 태그들(link, script, img)을 만나면 HTML 파싱을 멈추고 해당 리소스 파일을 서버로 요청합니다. 20 | 21 | - HTTP 1.1과 HTTP 2.0의 차이점은 1.1은 하나의 커넥션당 하나의 요청, 응답만 가능하지만 2.0은 하나의 커넥션에 다중 요청, 다중 응답이 가능합니다. 그래서 여러 리소스의 동시 전송이 가능하니까 페이지 로드 속도가 50% 빠르다고 합니다. 22 | 23 | ### 2. HTML을 파싱하여 DOM을 생성 24 | 25 | 받아온 HTML은 단순한 문자열로 이루어진 텍스트입니다. 그걸 브라우저가 이해할 수 있는 자료구조 (객체)로 바꾸어서 메모리에 저장해야 합니다. 이것을 파싱 과정이라고 하는데 파싱의 간략한 과정은 아래와 같습니다. 26 | 27 | - HTML 문자열 자체를 메모리에 저장하고, 저장된 바이트(2진수)를 인터넷을 경유해서 응답합니다. 28 | - 바이트 형태의 HTML 문서는 meta 태그의 charset 어트리뷰트에 의해 지정된 인코딩 방식을 기준으로 문자열로 변환합니다. 29 | - 문법적 의미를 갖는 코드의 최소 단위인 토큰으로 분해합니다. 30 | - 토큰들을 객체화해서 노드를 생성합니다. 31 | - HTML 노드 간의 부자 관계를 반영해서 모든 정보를 저장한 DOM을 생성합니다. 해당 자료구조는 트리 자료구조입니다. 32 | 33 | ### 3. CSS 파싱, CSSOM 생성 34 | 35 | HTML을 처음부터 한 줄씩 파싱하다가 `` 태그나 `