TIL 20210930 [항해99 15일차]

Arong·2021년 9월 30일
0

자바스크립트 문법

  • 변수와 상수

[변수 생성의 3단계]
선언 → 초기화 → 할당

  • 선언: 실행 컨텍스트에 변수 객체를 등록 (스코프가 참조하는 대상이 되도록!)
  • 초기화: 변수 객체에 등록된 변수를 위해 메모리에 공간을 확보 (여기서 변수는 보통 undefined로 초기화!)
  • 할당: undefined로 초기화된 변수에 실제 값을 할당

(1) var
※ var는 가급적 사용하지 않는 게 좋다!

  • var로 선언한 변수는 블록 스코프가 아니라 함수 수준 스코프를 가진다.

  • var는 선언과 초기화를 한번에 한다!

  • 재선언이 가능하다.

  • 선언하기 전에도 사용할 수 있다.

    ```jsx
    // var는 이런 식의 사용도 가능합니다. 괴상하죠!
    // var name은 선언! name = "perl"은 할당!
    function cat(){
    	name = "perl";
    	alert(name);
    	var name;
    }
    
    cat();
    ```

    p.s. 파일을 읽어오는 것과 실제로 돌아가게 하는 건(=실행) 다르다. 파일을 읽어오는 건 파일 전체를 싹 확인, 실제로 돌아가게 하는 건 코드를 한줄 한줄 읽어서 동작하게 하는 것.

  • 코드 블럭을 무시합니다. (var는 함수의 최상위로 호이스팅 됩니다.(-> 선언을 밑에 해도 동작 가능!) 선언은 호이스팅 되고 할당은 호이스팅 되지 않습니다.)

// var name은 함수의 최상위로 호이스팅되기 때문에, 실행될 일 없는 구문 속에 있어도 선언이 됩니다.
(자바스크립트가 동작하기 전에 코드를 한 번 훑는데 그 때, var로 선언된 코드를 전부 최상위로 끌어올려버립니다. 
동작해선 안되는 구문이라도... 몽땅..!)

function cat(){
	name = "perl";
	// 이 if문 내로는 절대 들어올 일이 없죠!
	if(false) {
		var name;
	}
	alert(name);
}

cat();

(2) let

  • 자바스크립트에서 변수를 생성할 때 쓰는 키워드
  • block-scope를 갖는다.
    • {}안에서 선언하면 {} 안에서만 쓰고 바깥에선 쓸 수 없어요!
  • 재선언은 불가, 재할당은 가능!
// 재할당은 가능!
let cat_name = 'perl';
cat_name = '펄이';

// 재선언은 오류!
let cat_name = 'perl';
let cat_name = '펄이'; 

(3) const

  • 자바스크립트에서 상수를 생성할 때 쓰는 키워드
  • block-scope를 갖는다.
    • {}안에서 선언하면 {} 안에서만 쓰고 바깥에선 쓸 수 없어요!
  • 재선언 불가, 재할당도 불가! (⇒ 선언과 동시에 할당해요!)
    // 재할당 오류!
    const cat_name = 'perl';
    cat_name = '펄이';
    
    // 재선언도 오류!
    const cat_name = 'perl';
    const cat_name = '펄이';
    
    // 선언과 동시에 할당 되기 때문에 값을 안줘도 오류가 납니다.
    // declare!
    const cat_name;

(4) TDZ(Temporal Dead Zone) = 일시적 사각지대

  • let과 const도 호이스팅이 될까?
    간단하게 말하자면...
    var과 let, const의 차이점 중 하나는 변수가 선언되기 전에 호출하면 ReferenceError가 나는 점이다.
    Q. 왜 에러가 날까? 호이스팅이 안 된 걸까?
    A. 호이스팅(=선언 끌어 올리기)은 된다! 다만, 선언한 후, 초기화 단계에서 메모리에 공간을 확보하는데, 선언을 호이스팅해도 초기화 전까지 메모리에 공간이 없죠! 그래서 변수를 참조할 수 없기 때문이다. 이걸 TDZ라고 해요!
  • 그럼 let, const는 호이스팅이 되지 않는 건가?
    → 답은 호이스팅이 된다!
  • 그럼 왜 레퍼런스 에러가 날까?
    → TDZ 때문에 그렇다!
  • 3줄요약...
    → let, const 선언도 호이스팅 된다.
    → 스코프에 진입할 때 변수를 만들고, TDZ가 생성되지만 코드 실행이(=실행 컨텍스트가) 변수가 있는 실제 위치에 도달할 때까지 엑세스를 못할 뿐.
    → 면접에 자주 나온다... 😢

[알면 재미있는 이야기: 변수명]
변수명은 숫자로 시작할 수 없고, _와 $를 제외한 특수문자를 쓸 수 없어요!
그 외의 모든 것은 가능합니다. 심지어, 한글도 가능해요. 🤭

  • 자료형

자바스크립트는 8가지 기본 자료형을 지원한다. 객체를 제외한 나머지 7가지를 원시형(primitive type)이라고 부른다. typeof 연산자로 자료형을 알아낼 수 있어요. 🙂

  • 정수, 부동 소수점을 저장하는 숫자형: -(2^53-1) ~ (2^53-1)까지 지원
  • 아주 큰 숫자를 저장하는 BigInt형
  • 문자열을 저장하는 문자형
  • 논리 값 (true/false. boolean형)
  • 값이 할당되지 않음을 나타내는 독립 자료형 undefined
  • 값이 존재하지 않음을 나타내는 독립 자료형 null
  • 복잡한 자료구조(숫자, 문자 한번에 넣을 수 있음)를 저장하는 데 쓰는 객체형
  • 고유 식별자(하나 밖에 없는 값)를 만들 때 쓰는 심볼형 => 라벨같은 것. ex) let cat = Symbol("cat"); let cat2 = Symbol("cat"); -> console.log( cat == cat2 ); -> False! =>즉, 같은 단어를 쓰는 건 상관 없지만, symbol이 붙으면 같은 단어여도 다른 값이 된다.

[알아두면 더 좋은 Tip: 엄격 모드]
자바스크립트는 엄청 많은 버전이 있다! 우리가 들어본 ES6도 사실 자바스크립트의 한 버전일 뿐이다. (보통 이야기하는 하위 버전 자바스크립트는 ES3, 최신이다! 모던이다! 하면 ES6 이상을 가리킨다!)
자바스크립트는 하위 호환성에 도른 언어라, 코드를 읽을 때 모던한 방식보다는 하위 호환에 초점을 맞춰 동작한다. 최신 기능이라기에 써봤는데, 오류를 뿜어낼 수 있단 소리다. 😢
그럴 때 쓰는 게 엄격 모드 use strict이다. 'use strict;'를 스크립트 최상단에 써주면 모던 자바스크립트에서 지원하는 모든 기능을 활성화해준다!

  • 객체란?
  • 오직 한 타입의 데이터만 담을 수 있는 원시형과 달리, 다양한 데이터를 담을 수 있다.
  • key로 구분된 데이터 집합, 복잡한 개체를 저장할 수 있다.
  • {...} ← 중괄호 안에 여러 쌍의 프로퍼티를 넣을 수 있다.
    • 프로퍼티는 key : value로 구성
    • key에는 문자형(1,2,3 같은 숫자도 문자형으로 들어가는 것), value에는 모든 자료형이 들어갈 수 있음 => key에 대응하는 값 가져오는 방법 ex) let a = {b:1, c:2},
      첫번째 방식: a.b => 1
      두번째 방식: a['b'] => 1
  // 객체 생성자로 만들기(new)
  let cat = new Object();
  // 객체 리터럴로 만들기
  // 중괄호로 객체를 선언하는 걸 리터럴(데이터 값 그자체)이라고 하는데, 객체 선언할 때 주로 씁니다!
  let cat = {};
  • 상수는 재할당이 안 된다고 했지만...
  • const로 선언된 객체는 수정될 수 있다. 😖 -> 새로운 메모리에서 값이 변하고 주소값은 변하지 않아서 const 선언 객체는 수정 가능
  • const로 선언된 객체는 객체에 대한 참조를 변경하지 못한다는 것을 의미!
  • 즉, 객체의 프로퍼티는 보호되지 않아요!(=> const 선언 객체는 수정 가능하다는걸 이렇게 표현한다.)
// my_cat이라는 상수를 만들었어요!
const my_cat = {
	name: "perl",
	status: "좀 언짢음",
}

my_cat.name = "펄이"; 

console.log(my_cat) // 고양이 이름이 바뀌었죠!

// 여기에선 에러가 날거예요. 프로퍼티는 변경이 되지만, 객체 자체를 제할당할 순 없거든요!
my_cat = {name: "perl2", status: "많이 언짢음"};

p.s. 원시형은 메모리에 할당된 값이 들어가지만 객체형은 새로운 객체 메모리가 생기고, 들어가야 할 메모리엔 객체 주소가 들어가는 것인데 이걸 '객체에 대한 참조가 들어간다'라고 표현한다.

  • 함수

자바스크립트는 함수를 특별한 값 취급을 한다.
자바스크립트는 ()가 있으면 함수를 실행하고 ()가 없으면 함수를 문자형으로 바꿔 출력하기도 한다. (함수를 값으로 취급하는 것!) 이걸 응용하면, 함수를 복사할 수 있고, 또 매개변수처럼 전달할 수 있다.
함수는 기본적으로 undefined를 반환한다. return으로 어떤 값을 넘겨주지 않는다면!

  • 함수 선언문과 함수 표현식

(1) 함수 선언문 => 독립된 구문으로 존재!

// 이렇게 생긴 게 함수 선언문 방식으로 함수를 만든 거예요.
function cat() {
	console.log('perl');
}

(2) 함수 표현식

// 이렇게 생긴 게 함수 표현식을 사용해 함수를 만든 거예요.
let cat = function() {
	console.log('perl');	
}

// 물논 화살표 함수로 써도 됩니다.
// 다만 주의하실 점! 화살표 함수는 함수 표현식의 단축형이라는 거! 주의하세요! :) 
let cat2 = () => {
	console.log('perl2');
}

p.s. 화살표 함수에선 this를 사용할 때 자기 자신이 아닌 '부모'를 불러온다.

  • 함수 선언문 vs 함수 표현식
    • 함수 선언문으로 함수를 생성하면 독립된 구문으로 존재
    • 함수 표현식으로 함수를 생성하면 함수가 표현식의 일부로 존재
    • 함수 선언문은 코드 블록이 실행되기 전에 미리 처리되어 블록 내 어디서든 사용할 수 있다.
    • 함수 표현식은 실행 컨텍스트가 표현식에 닿으면 만들어진다. (변수처럼 처리되는 것!)
  • 지역 변수와 외부 변수
  • 지역 변수
    • 함수 내에서 선언한 변수
    • 함수 내에서만 접근 가능
  • 외부 변수(global 변수라고도 합니다.)
    • 함수 외부에서 선언한 변수
    • 함수 내에서도 접근할 수 있다.
    • 함수 내부에 같은 이름을 가진 지역 변수가 있으면 사용할 수 없다.
let a = 'a';
let b = 'b';
let c = 'outter!';
const abc = () => {
	let b = 'inner!';
	c = 'c';
	let d = 'd';
	console.log(a, b, c, d);
}

console.log(a, b, c, d); // a, b, outter, undefined

abc(); // a, inner, c, d

console.log(a, b, c, d); // a, b, c, undefined

p.s. 내부변수가 외부변수보다 사용하는 우선순위가 더 높다. 외부변수랑 내부변수가 같은 명으로 쓰이면 내부변수 우선으로 적용!

  • 콜백 함수

함수를 값처럼 전달할 때, 인수로 넘겨주는 함수를 콜백 함수라고 한다!

  • 예시
const playWithCat = (cat, action) => {
	action(cat);
}

const useBall = (cat) => {
	alert(cat+"과 공으로 놀아줍니다.");
}

//playWithCat 함수에 넘겨주는 useBall 함수가 콜백 함수입니다!
playWithCat("perl", useBall);

p.s. 매개변수(=parameter)와 인수(=argument)는 사실 다르다... 매개변수는 인수를 복사한 값이다. 그래서 원본 값이 손상되지 않는다.

  • Prototype
  • 자바스크립트와 클래스 기반 객체 지향 언어
    [주의!]
    자바스크립트는 동적 언어이고 클래스가 없는 언어이다.
    클래스 기반 언어를 사용하다 자바스크립트를 접하면 특히 혼란스러워하는 부분!
    분명 기초 강의에서는 클래스를 배웠는데...?
    → 그 클래스는 ES2015(ES6)부터 지원하는 키워드이다.
    클래스 기반 언어가 말하는 클래스를 자바스크립트가 흉내낸 것 뿐!
    그럼 자바스크립트는 정확히 뭐지?
    자바스크립트는 프로토타입 기반 동적 언어이다. 🙂

  • 객체 생성 방법이 다르다!
    [클래스 기반] ex) java, c++, ...
    객체 생성 전에 클래스를 정의하고 이를 통해 객체(인스턴스)를 생성

    [자바스크립트]
    클래스 없이 객체를 생성(리터럴과 생성자)

  • 프로토타입이란?
    => 사실 디자인 패턴 중 하나, 원본 객체가 있고 원본을 복사해서 사용하는 것!

자바스크립트의 모든 객체는 자신의 부모 객체와 연결되어 있다. 좀 더 정확히는 부모 객체의 원형과 연결!(부모 객체의 프로토타입)
마치 객체 지향에서의 상속 개념처럼 부모 객체의 프로퍼티나 메소드를 상속받아 쓸 수 있다.
(실제로는 상속보다 위임에 가깝다고 하지만, 통상적으로 상속한다고 표현)
이런 부모 객체를 프로토타입 객체, 혹은 그냥 프로토타입이라고 부른다. 🙂
그리고 부모 객체를 참조하는 걸 두고 프로토타입 링크라고 한다.

p.s. <자바스크립트와 엮어서 생각할 때 알아야할 것!>
1. 객체는 함수를 사용해서 만들어진다. but, 자바스크립트는 프로토타입 기반이다. => 객체는 함수를 사용해서 만들어지는데 객체는 함수의 프로토타입 객체를 복사해서 생성한다.
2. 객체는 자신이 어디서 복제가 됐는지 알고 있다.


오늘 배운 프로토타입은 기술면접에서 많이 나온다고 한다... 간단하게 정리하자면 "프로토타입은 자바스크립트가 어떻게든 객체를 저렴하게, 리소스 낭비 없이 생성 해보려는 노력이다!"
오늘부터 리액트 심화주차를 시작하게 됐는데 기본주차때와 또 다른 내용들을 공부하고있어서 너무 어렵다ㅠㅠㅠ 컴포넌트가 작게 쪼개져서 복잡해진 느낌이지만 얼른 익숙해져서 쪼개진 컴포넌트의 편리함을 느낄 수 있길...!

profile
아롱의 개발일지

0개의 댓글

관련 채용 정보