-
[멋쟁이사자처럼] 프론트엔드 스쿨 7기 - 29일차 기록 및 복습Front-end 개발 2023. 8. 16. 08:35
목차
1. JavaScript 전개구문
2. JavaScript 디스트럭쳐링
3. JavaScript this 키워드
4. 함수 심화
5. 스코프
6. 잡답
1. JavaScript 전개구문
1-1. 전개구문
- spread syntax
- Spread 문법은 배열이나 객체와 같은 데이터 구조를 확장할 때 사용하는 문법
1-2. 배열의 전개구문
- 배열의 전개 구문은 대괄호([]) 안에서 세 개의 점(...)을 사용하여 배열을 확장한다.
- 전개구문을 활용하여 배열의 값만을 복사해 새로운 배열을 만들 수도 있다.
- 이렇게 생성된 배열은 기존의 객체 자료형처럼 참조를 공유하지 않고 완전히 별개인 새로운 값이 할당된다.
1-3. 객체의 전개구문
- 객체의 전개 구문은 중괄호({}) 안에서 세 개의 점(...)을 사용하여 배열을 확장한다.
- 전개되는 객체들 중에 같은 이름의 key가 있다면, key 의 값은 나중에 온 객체의 키값으로 업데이트 할 수 있다.
const me = { name: "철수", address: "서울" }; const newAddress = {address : "서귀포시"}; const newMe = {...me, name: "길수", ...newAddress}; console.log(newMe); // {name: '길수', address: '서귀포시'}
2. JavaScript 디스트럭쳐링
2-1. Destructuring (구조분해할당)
- destructuring MDN 번역문을 보면 '구조 분해 할당'으로 나온다. 뜻은 네이버 기준으로 '...의 구조를 파괴[해체]하다'
- 디스트럭쳐링은 ES6 부터 지원하는 문법으로, 배열이나 객체아 같은 데이터 구조를 분해하여 변수에 할당하는 표현식
- 더 간결하고 빠르게 작성할 수 있는 구문으로 사용된다.
2-2. 객체의 디스트럭쳐링
- 디스트럭쳐링의 기본 구조
let obj = {one: 1, two : 2}; let myNum = obj.one; console.log(myNum); let obj = {one: 1, two : 2}; let {one: myNum} = obj; console.log(myNum);
- 생김새가 정확히 객체 리터럴과 동일하나, 왼쪽에 있으면 디스트럭쳐링이고 오른쪽에 있으면 객체 리터럴이다.
- 위 예제에서 디스트럭쳐링의 {one: myNum} 은 myNum 이 데이터의 이름을, one 이 데이터의 값을 나타냄
// 왼쪽이 디스트럭처링, 오른쪽이 객체 리터럴이다. let {one:myNum} = {one:1}; console.log(myNum); // 1
- 디스트럭쳐링은 이름과 콜론을 생략할 수 있다.
/* let food1, food2, food3; const categories = {food1 : '과일', food2 : '채소', food3 : '육류'}; food1 = categories.food1; food2 = categories.food2; food3 = categories.food3; */ const { food1, food2, food3 } = { food1: '과일', food2: '채소', food3: '육류' }; console.log(food1, food2, food3);
- 실무에서도 그리고 react 에서도 많이 사용한다.
- 디스트럭쳐링을 이용하면 반복과 불필요한 변수 생성을 줄여 코드를 깔끔하게 작성할 수 있다.
2-3. 배열의 디스트럭쳐링
- 배열의 경우는 객체의 디스트럭처링과 다르게 변수의 이름이 달라도 순서대로 들어간다.
const arr = [1, 2, 3]; const [a, b, c] = arr; console.log(a); // 1 console.log(b); // 2 console.log(c); // 3
2-4. 함수의 디스트럭쳐링
- 함수의 디스트럭쳐링은 함수의 매개변수를 분해해서 변수에 할당하는 방법
- 객체로 받는 것도 가능함
// 함수에서 배열의 스트트럭쳐링 function myFunc([a, b]) { console.log(a); console.log(b); } const arr = [1, 2]; myFunc(arr); // 함수에서 객체의 스트트럭쳐링 function myFunc({a, b}) { console.log(a); console.log(b); } const obj = {a:1, b:2}; myFunc(obj);
3. JavaScript this 키워드
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/this
3-1. this 키워드
- mdn 설명은 생각보다 불친절하다.
- this는 객체를 가리키는 참조 변수이다. this는 호출 위치에 따라 다른 값을 출력하기 때문에 우리에게 혼란을 준다.
- 보통은 함수 안에서 사용된다.
function a() { console.log(this); } a(); // window 객체 const myObj = { val1: 100, func1() { console.log(this); } } myObj.func1();
- Window 객체: 브라우저 환경의 전역 공간을 의미한다. Node.js 환경에서의 전역공간은 global 이란 이름을 가진다.
- window 는 생략이 가능하며, 함수 a()를 선언하면 window 객체에 생성되어 window.a() 와 같이 정의된다.
- 어떤 객체의 메소드가 아닌 단독 호출되는 함수의 this 는 전역공간을 참조하게 된다.
let myObj = { val1: 100, func1: function () { console.log(this); } } let test = myObj.func1; test() // Window 객체
- 기본적으로 this 는 함수를 호출하는 객체를 가르킴
- this가 가리키는 개체는? this 키워드를 가지고 이는 함수를 호출하는 개체
- 전역공간에서 호출하게되면 가리키는 것은 window 객체이다.
- 그렇기 때문에 전역공간에서 선언한 변수(var) 를 참조할 수 있다.
- let, const 는 전역 공간에 선언되지 않는다.
function sayName() { console.log(this.name); } var name = 'Hero'; let name2 = 'here'; const name3 = 'here'; // 전역으로 선언한 name 변수의 앞에는 window 가 생략되어 있습니다. // 때문에 window.name === "Hero" 가 성립합니다. let peter = { name: 'Peter Parker', sayName: sayName } let bruce = { name: 'Bruce Wayne', sayName: sayName } sayName(); peter.sayName(); bruce.sayName();
- 참고로, name 은 기본적으로 window 객체에 있는 속성이다.
- 전역공간에서 this 는 전역공간을 가리킨다.
- 함수 안에서의 this는 this 를 가지고 있는 함수를 호출하는 객체를 가리킨다.
- this 는 함수가 만들어질 때가 아닌 '실행'될 때 그 값이 결정된다.
- 다이나믹 스코핑 : 실행되야 알 수 있는 것
- Lexical 스코핑 : 문법적으로 알 수 있는 것
3-2. this 값을 사용자의 의도대로 조작하기
- apply(), call(), bind()
- call() 은 콤마를 통해서 인자를 전달해줄 수 있다.
3-3. call()
var peter = { name : 'Peter Parker', sayName : function(){ console.log(this.name); } } var bruce = { name : 'Bruce Wayne', } peter.sayName.call(bruce); // Bruce Wayne
- 아규먼트를 전달해줄 수 있다.
var peter = { name : 'Peter Parker', sayName : function(감탄사){ console.log(this.name + 감탄사); } } var bruce = { name : 'Bruce Wayne', } peter.sayName.call(bruce, '!'); // Bruce Wayne!
3-4. apply()
- call() 과 유일한 차이는 단일한 배열로 전달하는 아규먼트의 차이
- 배열 내부의 순서대로 아규먼트로 전달된다.
var peter = { name : 'Peter Parker', sayName : function(is, is2){ console.log(this.name+ ' is '+ is + ' or ' + is2); } } var bruce = { name : 'Bruce Wayne', } peter.sayName.apply(bruce, ['batman', 'richman']); // Bruce Wayne is batman or richman /* peter.sayName.apply(bruce, ['batman', 'richman']) 의 결과가 무엇이 될지 생각해보고 apply 를 call로 바꾸어 호출했을 때와 비교해 봅시다. */
3-5. bind()
- this가 고정된 새로운 함수를 반환한다.
function sayName(){ console.log(this.name); } var bruce = { name: 'bruce', sayName : sayName } var peter = { name : 'peter', sayName : sayName.bind(bruce) } peter.sayName(); // bruce bruce.sayName(); // bruce /* peter.sayName() 과 bruce.sayName() 의 결과 값이 무엇이 될지 생각해봅시다. */
- this에 바인딩되는 객체가 동적으로 결정되는 기명함수와 달리 화살표 함수의 경우 상위 스코프의 this 를 가리킵니다. 이러한 방식을 (정의된 코드를 보고 알수 있는) 렉시컬(Lexical) 스코프 라고 부릅니다.
const person = { name: 'hojun', age: 25, a() { console.log(this); // person console.log(this.name); // hojun function b() { console.log(this); // window console.log(this.name); // '' window (기존 window 의 name 은 빈문자열) function c() { console.log(this); // window console.log(this.name); // '' window (기존 window 의 name 은 빈문자열) } c(); } b(); } } person.a()
- 메소드로써 실행되는 함수는, 객체에 들어가있는 함수이기 때문에 객체를 가리킨다.
- a() 는 person 의 매소드다.
- b()와 c() 는 단독 호출되어 실행되는 함수는 window 객체를 가리킨다.
- a() 를 전역으로 선언하여 사용하면 전역공간에서 실행됬으며, 단독 호출되어 이것 또한 window 객체를 가리킨다.
const func = person.a; func(); // window
3-6. 화살표함수에서 this
- 화살표함수에서는 this 를 감싸고 있는 함수의 상위 스코프의 객체를 가리킨다.
// a에서 this = person // b에서 this = 상위스코프(상위에서 person을 보고있음) 즉 person // c에서 this = 상위스코프(상위에서 person을 보고있음) 즉 person const person = { name: 'hojun', age: 25, a(){ console.log(this); // {name: 'hojun', age: 25, a: ƒ} console.log(this.name); // hojun let b = () => { console.log(this); // {name: 'hojun', age: 25, a: ƒ} console.log(this.name); // hojun let c = () => { console.log(this); // {name: 'hojun', age: 25, a: ƒ} console.log(this.name); // hojun } c() } b() } } person.a()
- 화살표 함수를 피해야하는 경우 (this 가 전역을 가리키는 경우)
let 인세규정 = { 책:10, 영상콘텐츠:50 }; [100, 200, 300].map(e => e *(this.책/100), 인세규정); // [NaN, NaN, NaN] [100, 200, 300].map(e => this, 인세규정); // [Window, Window, Window]
3-7. forEach 문에서 this
- forEach 두번째인자로 this 의 인자로 사용할 수 있다.
- 두번째 인자를 빼면 전역에서 실행되기 때문에 window 를 가리킴
[1, 2, 3].forEach(function(){console.log(this)}, [10, 20, 30]) // [10, 20, 30] // [10, 20, 30] // [10, 20, 30]
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
3-8. map 에서 this
- 두번째인자로 thisArgs 를 줄 수 있다.
let 인세규정 = { 책:10, 영상콘텐츠:50 }; function 인세계산함수(e){ return e *(this.책/100) }; [100, 200, 300].map(인세계산함수, 인세규정); // [10, 20, 30]
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/map
3-9. 정리
- 메서드로 호출할 경우 this 는 멤버접근연산자 앞의 객체를 가리킨다. (예시: obj.foo())
- 함수로 호출한 경우 this 는 window(node는 global) 를 가리킨다.
- 화살표 함수의 경우 this 는 상위 스코프를 가리킨다.
- 생성자 함수 혹은 class 의 경우 this 는 인스턴스를 가리킨다.
4. 함수 심화
4-1. 구조분해할당을 이용한 아큐먼트 처리
- 매개변수에 디스트럭쳐링을 사용하려고 한다면, 매개변수에 빈 객체라도 할당을 해주어 초기화하여 예외처리를 한다.
(코딩 버릇을 가지자, 방탄코딩)- 디스트럭쳐링을 함수의 매개면수(파라미터)에서 이루어지고 있다.
{name, age, email} = { name: '재현', age: 25, email: 'jaehyun@something.com' }function printMe({ name, age, email } = {}) { console.log(`이름: ${name}, 나이: ${age}, 이메일: ${email}`); } const me = { name: '재현', age: 25, email: 'jaehyun@something.com' }; printMe(me);
4-2. rest 문법
- 함수의 매개변수에 ...를 붙이면 사용자가 제공한 모든 매개변수를 배열안에 넣도록 지정
- rest 문법을 사용할 때 주의할 점
(1) 매개변수에는 하나의 rest 만 존재할 수 있다.
(2) rest 는 반드시 함수 정의의 마지막 매개변수여야 한다.
function 함수2(a, b, ...c){ console.log(c) return Math.max(...c) } 함수2('hello', 'world', 10, 20, 30, 40) // [10,20,30,40] // 40 function 함수2([a, b], ...c){ console.log(a) console.log(b) console.log(c) } 함수2([1, 2], 10, 20, 30, 40) // 1 // 2 // [10, 20, 30, 40]
- 사용하는 위치에 따라 spread 와 rest 로 나뉜다.
- 함수의 마지막 매개변수에 사용되는 ...은 rest 문법으로 인식하고
- 자바스크립트 엔진은 일반적인 객체나 배열안에서 사용되는 ...은 spread 문법으로 인식한다.
4-3. 매개변수 초기화
- 함수의 매개변수는 선언과 동시에 파라미터 값을 할당하여 초기화도 가능하다.
- 매개변수의 초기화는 기본적으로 왼쪽에서 오른쪽으로 순서로 설정된다.
- 매개변수 초기화는 함수 선언에서 일어나지 아규먼트에서 일어나지 않는다. (아큐먼트의 초기화식은 무시하자)
function 함수3(a=10, b=20, c=30){ return a + b + c } console.log(함수3()) console.log(함수3(100)) console.log(함수3(100, 200)) console.log(함수3(100, 200, 300)) console.log(함수3(c=1000)) // 1030이 되어야 하는거 아니에요? // 1050 console.log(함수3(c=1000, a=2000)) // 3020이 되어야 하는거 아니에요? // 3030 // 값이 순서대로 들어갔습니다.
5. 스코프 scope
5-1. 스코프
-스코프란 변수의 접근성과 생존 기간을 제어하는 '생존 범위'를 의미한다.
const func1 = function(){ var a = 1; var b = 2; console.log(a + b); }; var a = 20; func1(); // 3
- 변수 a는 어디서든 접근 가능한 전역 변수임에도 불구하고 함수안밖의 a는 완전히 별개의 변수임을 알 수 있다.
- 함수안 a변수는 함수가 종료면 함수 스코프가 가비지 컬랙션으로 수거되기 때문에, 메모리상에서 자동으로 제거된다.
- 이렇듯 스코프는 이름이 충돌하는 문제를 덜어주고, 자동으로 메모리를 관리한다.
5-2. 스코프의 종류
(1) 전역 스코프 : 스크립트 어디서든 접근이 가능. 타인과 협업, 라이브러리 사용시 충돌의 가능성이 있다.
(2) 함수 스코프 : 함수 내부에서 정의된 변수와 매개변수는 함수 외부에서 접근할 수 없다.
(3) 블록 스코프 (ES6) : 중괄호 안에서만 접근 가능. 블록 내부에서 정의된 변수는 블록의 실행이 끝나면 해제됨
- 스코프 체이닝: 현재 스코프에서 찾을 수 없는 값을 찾기 위해 스코프를 이동하는 것
- 함수 스코프는 var 를 포함하여 절대 외부에서 내부로 접근이 불가능하다. (내부에서 외부 접근은 가능하다)
let z = 100; function sum(x){ // x는 매개변수(parameter)이면서 지역변수(local val) let y = 50; // y는 지역변수 z = z + y; return x + y; } console.log(sum(10)); // 10은 전달인자(argument) console.log(x); // 오류 console.log(y); // 오류 console.log(z); // 150 // 블록 레벨 스코프 if(true){ // for문이어도 마찬가지입니다. let k = 10; const t = 10; } console.log(k, t) // 오류 for(var i=0; i<10; i++) {} console.log(i); // 10 // scope chaining let a = 10; function outer() { let b = 20; function inner() { let c = 30; console.log(a, b, c); } inner(); console.log(a, b); } outer(); // 10 20 30 // 10 20
6. 잡담 시간
6-1. 신입으로 들어간 회사
- 처음 들어보면 선임의 코드를 분석하는 일을 시킨다.
- 회사에서 무지를 드러내지 않기 위해 숨기는 건 회사에서도 문제다.
- 질문을 많이 해라
- 어떻게 질문을 해야 욕을 먹지 않을까?
> 자기가 이해한 바를 이야기하고, 어떤 노력을 해봤는데, 이해가 안된다고 해야 한다.
> 충분한 고민을 해보고 질문한다는 걸 보여줘야 한다.
- 너무 고민하는 것은 마이너스다
> 업무에 지장이 가는 고민을 하면 안된다. (고민은 1시간 내로 해야 함)
> 계속 후벼파면서 다른 모르는 걸 찾다가 일을 못한다.
> 이러면 정해진 기간이 길어지면 선임이 왔을 때 진척은 없고 속상하다.
'Front-end 개발' 카테고리의 다른 글
[멋쟁이사자처럼] 프론트엔드스쿨 7기 - 31일차 기록 및 복습 (JSON, DOM) (0) 2023.08.18 JS 클로저 (0) 2023.08.18 [멋쟁이사자처럼] JS 실무자 노하우 코드 DB - typeof, isNaN, sort (0) 2023.08.08 [이력서] 직무(JD)분석 - 캐치테이블 (2) 2023.08.05 [이력서] 직무(JD)분석 - NAVER Glace CIC (1) 2023.08.05