[데브코스] 프론트엔드 엔지니어링 TIL(1일차)

홍건우·2023년 6월 2일
3

데브코스

목록 보기
1/17
post-thumbnail

프론트엔드 개발자 관련

프론트엔드 개발자의 핵심 역량

  • 커뮤니케이션: 프론트엔드 개발자는 다른 직군과 협업을 위한 소통 능력이 상당히 중요하다.
  • UI
  • 네트워크
  • 보안
  • 브라우저
  • 디자인

프론트엔드 개발자가 주의할 점

  • 컴퓨터 과학 파트를 무시하는 것: 알고리즘, 설계 패턴, 메모리와 같은 부분은 어떤 개발자도 꼭 필요함
  • CSS를 안하는 것: CSS를 대충 공부하는 것
  • 코더가 되는 것: 오로지 프레임워크나 라이브러리의 기능을 가져다 쓰기만 하는 것(복잡한 제품을 만들 수 없게 된다.)

변수

var

  • 변수를 선언하기도 전에 값 할당이 가능하다. (var hoisting: 선언의 위치와 상관 없이 제일 위로 선언을 끌어올림)
    hoisting: 인터프리터가 코드를 로드할때 변수의 선언을 항상 코드 내의 최상위로 끌어올리는 것을 의미함. 선언과 동시에 대입하는 코드는 호이스팅하지 않는다.(선언부는 호이스팅하지만 대입부는 호이스팅하지 않는다.)
  • 중복 선언이 가능하다.
    var name = 'Hong';
    console.log(name); //Hong
    
    var name = 'GunWoo';
    console.log(name); //GunWoo
  • 함수 레벨 스코프를 가진다.
    function func() {
    	if (true) {
    		var a = 5;
    		console.log(a); //5
    	}
    	console.log(a); //5
    }
    
    func()
    console.log(a); //Uncaught ReferenceError: a is not defined

let

  • 호이스팅이 발생하지만 JS내부에서 코드 실행 전 변수 선언만 해둘뿐 초기화는 코드 실행 과정에서 변수 선언문을 만났을 때 수행 →
    변수 선언 전에 값 할당이 불가능하다.(변수 선언문을 만나기 전까지는 변수 값을 참조할 수 없다.)
  • 중복 선언이 불가능하다.
  • 블록 레벨 스코프를 가진다.
    function func() {
    	if (true) {
    		let a = 5;
    		console.log(a); // 5
    	}
    	console.log(a); //Uncaught ReferenceError: a is not defined
    }
    
    func();
    console.log(a); //Uncaught ReferenceError: a is not defined

var과 let의 블록 스코프 차이

{
	var a = 3;
	console.log(a); //3
}

console.log(a); //3
{
	let a = 3;
	console.log(a); //3
}

console.log(a); //Uncaught ReferenceError: a is not defined

var과 let의 차이점

  • var은 변수를 선언하기도 전에 값 할당이 가능하다. (var hoisting: 선언의 위치와 상관 없이 제일 위로 선언을 끌어올림)
  • var은 block scope가 없다.

scope란 밖에서는 안이 보이지 않고 안에서만 밖을 볼 수 있는 것을 말한다.

상수

  • security (보안성이 좋다.)
  • thread safety (쓰레드들에서 동시에 값 변경이 불가능하다)
  • reduce human mistake (실수를 막을 수 있다.)
  • const문으로 선언한 상수 값은 수정할 수 없지만, 상수 값이 객체이거나 배열일 경우에는 프로퍼티 또는 프로퍼티 값을 수정할 수 있다.

자료형

  • Number
    • 정수, 실수 등 수를 의미함
    • NaN, Infinity도 Number타입이다
  • String: 문자열을 의미
  • Boolean: true, false
  • Object: 여러 값을 키-값 형태로 결합시킨 복합 타입
  • Array: 연관된 데이터를 연속적인 형태로 저장하는 복합 타입
  • Function
  • Undefined
    • 변수, 상수가 선언되었지만 값이 대입되지 않은 경우
    • 값이 정의되지 않은 상태를 의미
  • Null
    • null을 직접 지정한 경우
    • 해당 변수가 비어있음을 사용자가 의도적으로 나타낼 때 사용

false로 판정되는 값들: false, undefined, null, 0, NaN, ‘’(빈 문자열)

메모리

  • 할당 → 사용 → 해제
    3가지 과정을 거침
  • JS 엔진은 Garbage Collector를 통해 메모리를 정리한다.
  • Gabage Collector
    • Gabage Collection이라는 자동 메모리 관리 알고리즘을 통해 만들어진 객체
    • 사용하지 않는 메모리를 해제하는 역할을 한다.
      • Mark and Sweep Algorithm을 사용
        • 닿을 수 없는 주소를 더 이상 필요없는 주소로 정의하고 지우는 알고리즘
        • 예시
          let a = 126
          let b = a
          a = a + 1
          b = a + 1
          // 위의 경우 126을 참조하는 변수가 없기 때문에 GC가 126이 할당된 메모리를 정리한다.
  • JS에서 원시타입은 변경이 불가능하다. → 원시 타입의 값이 변경될 때는 새로운 메모리가 할당된다.
    let variable = 126 // 주소: 111
    let variable2 = variable //variable2는 variable의 주소를 가리키고 있는 상태(주소: 111)
    variable = variable + 1 // 주소:111의 값이 변경되지 않고 variable은 주소: 112를 가리킴(값은 127)
  • JS의Virtual Machine(가상 머신)의 메모리 모델
    • Heap: 참조타입이 들어감, 동적으로 크기 변경이 가능함
    • Call Stack: 원시타입이 들어감
    • 예시
      let a = 10; // call stack
      let b = 20; // call stack
      const arr = []; // Heap (call stack에서 생성된 배열 변수 arr이 Heap의 배열 영역을 메모리 주소를 참조)
      arr.push(5); // Heap 메모리를 변경하는 것이기 때문에 상수여도 push가 동작함
      arr.push(3);
      arr.push(1);

배열과 객체

배열

배열 생성

const arr1 = new Array();
const arr2 = [];
const arr3 = [1, 2, 3, 4, 5];
const arr4 = new Array(5);
const arr5 = new Array(5).fill(5); // [5, 5, 5, 5, 5]
const arr6 = Array.from(Array(5), function(v, idx) {
  return idx + 1;
}) // [1, 2, 3, 4, 5]

배열 요소 추가, 삭제

const arr = [1, 2, 3];
// push 배열 끝에 새로운 요소 추가
arr.push(4); // [1, 2, 3, 4]

// pop 배열 끝의 요소 삭제
arr.pop(); // [1, 2, 3]

// shift 배열 맨 앞의 요소 삭제
arr.shift(); // [2, 3]

// unshift 배열 맨 앞에 요소 추가
arr.unshift(1); // [1, 2, 3]

배열 관련 함수

const joinArr = [1, 2, 3, 4, 5, 6];
// join
console.log(joinArr.join(", ")); // 1, 2, 3, 4, 5, 6

// reverse
console.log(joinArr.reverse()); // [ 6, 5, 4, 3, 2, 1 ]
console.log(joinArr); // [ 6, 5, 4, 3, 2, 1 ] => 원본 배열에도 영향을 준다.

// concat
const a = [1, 2, 3];
const b = [4, 5, 6];
console.log(a.concat(b)); // [ 1, 2, 3, 4, 5, 6 ]

// slice
const arr = [1, 2, 3, 4, 5, 6];
// 첫 번째 인자: 시작점, 두 번째 인자: 끝나는 점
console.log(arr.slice(2, 4)); // [ 3, 4 ]
console.log(arr); // [ 1, 2, 3, 4, 5, 6 ] => 원본 배열이 변하지 않음

// splice: 중간의 요소 삭제
arr.splice(2, 2); // 첫 번째 인자: 시작점, 두 번째 인자: 삭제할 개수
console.log(arr); // [ 1, 2, 5, 6 ]

배열 순회

for (let i = 0; i < 5; i += 1) {
  console.log(arr[i]);
}

// 추천하는 방식
for (const item of arr) {
  console.log(item);
}

배열을 객체처럼 사용한다?

const arr = [1, 2, 3, 4, 5];
console.log(typeof arr); //object 출력 => 배열은 객체 타입이다.
arr['key'] = 'value';
console.log(arr); // [ 1, 2, 3, 4, 5, key: 'value' ]
console.log(arr.length); // 5 => key가 추가되었지만 배열의 길이는 변하지 않는다.

객체

여러 값을 키-값 형태로 결합시킨 복합 타입

객체 생성

const obj1 = new Object();
const obj2 = {};
const obj3 = {name: 'Gun', company: 'dev'};

객체 요소 추가, 삭제

const obj = {};
obj["email"] = "foxrain.gg@gmail.com"; // 요소 추가 방법1
obj.phone = '01012345678'; // 요소 추가 방법2
console.log(obj); // { email: 'foxrain.gg@gmail.com', phone: '01012345678' }

delete obj.phone;
console.log(obj); // { email: 'foxrain.gg@gmail.com' }

// 객체 요소 유무 확인 방법
console.log('email' in obj); // true
console.log('phone' in obj); // false

객체의 키, 값의 집합 구하기

const obj = {
  email: "foxrain.gg@gmail.com",
  phone: "01012345678",
};

// 키의 집합
console.log(Object.keys(obj)); // [ 'email', 'phone' ]
// 값의 집합
console.log(Object.values(obj)); // [ 'foxrain.gg@gmail.com', '01012345678' ]

객체 순회

const obj = {
  email: "foxrain.gg@gmail.com",
  phone: "01012345678",
};

// for in은 객체의 키 값을 순회함
for (const key in obj) {
  console.log(key, obj[key]);
	// 1번째 실행: email foxrain.gg@gmail.com
	// 2번째 실행: phone 01012345678
}

스코프와 클로저

스코프(유효 범위)

변수가 어느 범위까지 참조되는 지를 뜻함

const a = 5; // Global Scope
{
	const b = 3; // Local Scope
	console.log(a, b); // 5 3
}
console.log(a, b); // Error

클로저

함수가 선언된 환경의 스코프를 기억하여 함수가 스코프 밖에서 실행될 때에도 기억한 스코프에 접근할 수 있게 만드는 문법

function makeGreeting(name) {
  const greeting = "Hello, ";

  return function() {
    console.log(greeting + name);
  };
}

const world = makeGreeting("World!");
const gunwoo = makeGreeting("GunWoo");

world();
gunwoo();
  • greeting 변수는 지역 스코프라서 함수가 종료되면 메모리에서 사라지지만 word(), gunwoo()에서 사용할 수 있다.

은닉화

클로저를 사용하여 내부 변수와 함수를 숨길 수 있다.

function Counter() {
  let privateCounter = 0;
  function changeBy(val) {
    privateCounter += val;
  }

  return {
    increment: function() {
      changeBy(1);
    },
    decrement: function() {
      changeBy(-1);
    },
    getValue: function() {
      return privateCounter;
    },
  }
}

const counter = Counter();
const counter2 = Counter();

console.log(counter.getValue()); // 0
counter.increment();
counter.increment();
console.log(counter.getValue()); // 2
counter.decrement();
console.log(counter.getValue()); // 1

console.log(counter2.getValue()); // 0 => 별개의 클로저

클로저 관련 오류

function counting() {
  let i = 0;
  for (i = 0; i < 5; i += 1) {
    setTimeout(function () {
      console.log(i);
    }, i * 100);
  }
}

counting(); // 5가 다섯번 출력됨
// setTimeout의 대기시간이 끝나 callback fuction이 실행되는 시점에는 루프가 종료되어
// i가 5인 상태이기 때문이다.

해결방법 1

IIFE(Immediately Invoked Function Expression, 즉시 실행 함수)를 사용한다.

function counting() {
  let i = 0;
  for (i = 0; i < 5; i += 1) {
    (function (number) {
      setTimeout(function () {
        console.log(number);
      }, number * 100);
    })(i);
  }
}

counting(); //0 1 2 3 4 출력

해결방법 2

let을 사용한다. ⇒ let은 블록 수준 스코프이기 때문에 매 루프마다 클로저가 생성된다.

function counting() {
  for (let i = 0; i < 5; i += 1) {
    setTimeout(function () {
      console.log(i);
    }, i * 100);
  }
}

counting(); //0 1 2 3 4 출력
profile
컴퓨터공학과 학생입니다

2개의 댓글

comment-user-thumbnail
2023년 6월 2일

앞으로도 좋은 글 부탁드립니다!

답글 달기
comment-user-thumbnail
2023년 6월 2일

같이 TIL 열심히 써 봐요 ~ 😎

답글 달기