## JavaScript 기본 문법
선언 → 초기화 → 할당
- 선언: 실행 컨텍스트에 변수 객체를 등록 (스코프가 참조하는 대상이 되도록)
- 초기화: 변수 객체에 등록된 변수를 위해 메모리에 공간을 확보 (여기서 변수는 보통 undefined로 초기화됨)
- 할당: undefined로 초기화된 변수에 실제 값을 할당
(var는 가급적 사용하지 않는 게 좋다)
{}
안에서 선언하면 {}
안에서만 쓰고 바깥에선 쓸 수 없다. // 재할당은 가능!
let cat_name = 'perl';
cat_name = '펄이';
// 재선언은 오류!
let cat_name = 'perl';
let cat_name = '펄이';
{}
안에서 선언하면 {}
안에서만 쓰고 바깥에선 쓸 수 없다. // 재할당 오류!
const cat_name = 'perl';
cat_name = '펄이';
// 재선언도 오류!
const cat_name = 'perl';
const cat_name = '펄이';
// 선언과 동시에 할당 되기 때문에 값을 안줘도 오류가 난다.
// declare!
const cat_name;
let과 const도 호이스팅이 될까?
var과 let, const의 차이점 중 하나는 변수가 선언되기 전에 호출하면 ReferenceError
가 난다는 점이다.
Q. 왜 에러가 날까? 호이스팅이 안 된 걸까?
A. 호이스팅(=선언 끌어 올리기)은 되지만 선언한 후, 초기화 단계에서 메모리에 공간을 확보하는데, 선언을 호이스팅해도 초기화 전까지 메모리에 공간이 없다.
그래서 변수를 참조할 수 없기 때문에 에러가 난다.
이걸 TDZ라고 한다.
자바스크립트는 8가지 기본 자료형을 지원합니다!
객체를 제외한 나머지 7가지를 원시형(primitive type)이라고 부른다.
자료형은typeof
연산자로 알아낼 수 있다.
숫자형
: -(2^53-1) ~ (2^53-1)까지 지원BigInt형
문자형
boolean형
)undefined
null
객체형
심볼형
{...}
← 중괄호 안에 여러 쌍의 프로퍼티를 넣을 수 있다.key : value
로 구성 // 객체 생성자로 만들기
let cat = new Object();
// 객체 리터럴로 만들기
// 중괄호로 객체를 선언하는 걸 리터럴이라고 하는데, 객체 선언할 때 주로 씁니다!
let cat = {};
// my_cat이라는 상수를 만들었어요!
const my_cat = {
name: "perl",
status: "좀 언짢음",
}
my_cat.name = "펄이";
console.log(my_cat) // 고양이 이름이 바뀌었죠!
// 여기에선 에러가 날거예요. 프로퍼티는 변경이 되지만, 객체 자체를 제할당할 순 없거든요!
my_cat = {name: "perl2", status: "많이 언짢음"};
자바스크립트는 함수를 특별한 값 취급한다.
자바스크립트는 ()가 있으면 함수를 실행하고 ()가 없으면 함수를 문자형으로 바꿔 출력하기도 서슴치 않기때문. (함수를 값으로 취급하는 모습)
이걸 응용하면, 함수를 복사할 수 있고, 또 매개변수처럼 전달할 수 있다.
// 이렇게 생긴 게 함수 표현식을 사용해 함수를 만든 거예요.
let cat = function () {
console.log('perl');
}
// 이렇게 생긴 게 함수 표현식을 사용해 함수를 만든 거예요.
let cat = function () {
console.log('perl');
}
// 물논 화살표 함수로 써도 됩니다.
// 다만 주의하실 점! 화살표 함수는 함수 표현식의 단축형이라는 거! 주의하세요! :)
let cat2 = () => {
console.log('perl2');
}
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
함수를 값처럼 전달할 때, 인수로 넘겨주는 함수를 콜백 함수라고 한다.
const playWithCat = (cat, action) => {
action(cat);
}
const useBall = (cat) => {
alert(cat+"과 공으로 놀아줍니다.");
}
//playWithCat 함수에 넘겨주는 useBall 함수가 콜백 함수입니다!
playWithCat("perl", useBall);
[주의!]
- 자바스크립트와 클래스 기반 객체 지향 언어
자바스크립트는 동적 언어이고 클래스가 없는 언어이다.
(클래스 기반 언어를 사용하다 자바스크립트를 접하면 특히 혼란스러워하는 부분)
자바스크립트의 클래스는 ES2015(ES6)부터 지원하는 `키워드`이다.
클래스 기반 언어가 말하는 클래스를 자바스크립트가 흉내낸 것 뿐이다.
"자바스크립트는 프로토타입 기반 동적 언어이다."
- 객체 생성 방법이 다르다!
[클래스 기반]** ex) java, c++, ...
> 객체 생성 전에 클래스를 정의하고 이를 통해 객체(인스턴스)를 생성
[자바스크립트]
> 클래스 없이 객체를 생성(리터럴과 생성자)
자바스크립트의 모든 객체는 자신의 부모 객체와 연결되어 있다.
좀 더 정확히는 부모 객체의 원형하고 연결되어 있다.(부모 객체의 프로토타입)
마치 객체 지향에서의 상속 개념처럼 부모 객체의 프로퍼티나 메소드를 상속받아 쓸 수 있다.
이런 부모 객체를 프로토타입 객체, 혹은 그냥 프로토타입
이라고 부른다.
그리고 부모 객체를 참조하는 걸 두고 프로토타입 링크
라고 한다.
// animal이라는 객체를 하나 만들었습니다!
let animal = {
leg: 4,
legCount() {
console.log(this.leg); // this는 animal을 의미합니다.
}
};
// 또 다른 객체 cat을 만들었고요!
// animal을 프로토타입 상속 받아올 거예요. (__proto__를 씁니다.)
let cat = {
__proto__:animal, // cat의 프로토타입은 animal!
cute: true,
};
// 프로토타입을 설정해주어서 cat은 animal의 메소드와 프로퍼티를 사용할 수 있어요.
cat.legCount();
console.log(cat.leg);
// cat만 가지고 있는 프로퍼티도 있고요!
console.log(cat.cute);
// animal은 cat의 속성을 가져올 수 없어요!
console.log(animal.cute);
> 위 예제에서 animal은 cat의 프로토타입 객체이다.
cat의 프로토타입은 animal이라고도 한다.
> cat.legCount()에서 실행되는 legCount는 animal에서 상속된 메소드이다.
→ animal의 메소드와 속성이 복사되어 cat에 들어가는 게 아님
> animal을 상속 받은 cat, cat을 상속받은 다른 객체를 만들 수도 있다.
→ 이런 식으로 상속이 쭉쭉 내려가는 걸 '프로토타입 체인'이라고 불러요.
> 순환 참조는 되지 않는다. (animal은 cat을 상속받은 객체를 상속할 수 없음)
+ 추가
[프로토타입 객체와 프로토타입 링크]
위 예제에서 우리는 두 가지 프로토타입을 배웠다.
하나는 프로토타입 객체, 또 하나는 프로토타입 링크([[Prototype]]
(숨김 프로퍼티)가 참조하는 값과 __proto__
)이다.
아직까지 면접 질문에 자주 출몰하고, 프로토타입 링크를 이야기할 때 __proto__
를 써서 이야기 하지만, __proto__
를 사용하는 방식은 구식이에요. (deprecated되었다.(링크→))
면접을 대비한다면 위 예제처럼 __proto__
로 직접 접근하는 방식을 알아두는 편이 좋지만, 그게 아니라면 가급적 Object.getPrototypeOf()
를 이용해 참조하고, 프로토타입 체인에 연결할 때는 Object.create()
를 이용해 연결하자!