5 분 소요

[FE] 데브코스 Day 1 ~~~

프론트엔드 개발자란…?

프론트 개발자는 브라우저에서 동작하는 UI를 개발하는것이다.

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

필요한 것

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

주의할 것

  • CS를 공부하지 않는 것
  • CSS를 안하는 것
  • 코더가 되는 것

변수

var

  • 변수를 선언하기도 전에 값 할당이 가능하다.
  • 중복 선언이 가능하다.
var name = '박경빈';
console.log(name); //박경빈

var name = '홍길동';
console.log(name); //홍길동
  • var은 function-scoped이다.

let

  • 변수 재선언은 불가능하다.
  • 재할당은 가능하다.
  • let은 block-scoped이다.

const

  • 변수 재선언, 재할당 모두 불가능하다.
  • const는 block-scoped이다.

var과 let의 블록 스코프 차이

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

console.log(a); //3

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

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

자료형

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

메모리

  • 할당 => 사용 => 해제 (3가지 과정)

  • JS 엔진은 Garbage Collector를 통해 메모리를 정리한다.

  • Gabage Collector

    • Gabage Collection이라는 자동 메모리 관리 알고리즘을 통해 만들어진 객체

    • 사용하지 않는 메모리를 해제하는 역할을 한다.

      • Mark and Sweep Algorithm을 사용

        • 쓰지않는 주소를 필요없는 주소로 인지하고 삭제하는 알고리즘

        • 예시

          let a = 126
          let b = a
          a = a + 1 // a = 127
          b = a + 1 // b = 127
          // 위의 경우 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] 5로 초기화 해준다. 
const arr6 = Array.from(Array(5), function(v, k) {
  return k + 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
// 중간의 요소를 잘라서 가져오고 싶다면 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 출력

작년에 클로저에 대해서 공부를 했었는데 이번에 다시 공부해보니.. 하나도 기억이 안나는거 같다.. 더 열심히 복습하고 공부해야할거같다.

밑에는 작년에 정리했던 클로저 글이다.

https://pkb9239.github.io/javascript/closure/

댓글남기기