[패스트캠퍼스] 프론트엔드 인강 환급 챌린지(4) JavaScript - 객체 안에 함수 넣기, 프로토타입과 ES6클래스
수강한 클립명
(1) 14. 객체 - 객체 안에 함수 넣기
(2) 30. 프로토타입과 클래스 - 객체 생성자
(3) 32. 프로토타입과 클래스 - ES6 Class
객체 안에 함수 넣기
아래 예제 코드에 대해 간단 설명 하겠습니다.
먼저 say : function say() 함수 안에 있는 this는 객체 안의 자기 자신을 가리킵니다. 즉 아래 코드에서의 this는
dog 객체 자기 자신을 가리키게 됩니다. this.sound는 dog.sound와 같습니다.
say : function() 함수는 위의 say : function say() 와 같은 역할을 합니다. 좀 더 간결하게 사용할 수 있다는 것만
알아두시면 됩니다.
say() 함수도 마찬가지입니다. 똑같이 동작하지만, 이렇게 더 간결하게 사용할 수 있습니다.
하지만 say : () => {} 와 같은 화살표 함수는 위와 같이 동일하게 동작하지 않습니다.
TypeError: cannot read property 'sound' of undefined. 오류를 출력하게 되는데, 화살표 함수는
this 객체를 읽지 못하기 때문입니다. 즉, 화살표 함수는 this를 자기가 속해 있는 곳으로 연결을 하지 않습니다.
this가 function 키워드로 생성한 일반 함수와 화살표 함수의 가장 큰 차이점입니다.
화살표 함수는 function 키워드에 비해 구문이 짧고 자신의 this, arguments, supter 또는 new.target을 바인딩하지 않습니다. 화살표 함수는 항상 익명입니다. 그래서 화살표 함수는 메소드 함수가 아닌 곳에 가장 적합합니다.
그래서 생성자로서는 사용할 수 없습니다.
좀 더 자세한 내용은 MDN링크를 참조하면 좋을 것 같습니다.
const dog = {
name: '멍멍이',
sound: '멍멍!',
say: function say() {
console.log(this.sound);
//this는 객체 안의 자기 자신을 가리킨다. 즉 여기서 this는 dog객체를 가리킨다.
},
// 똑같이 작동함!!
say: function() {
console.log(this.sound);
},
say() {
console.log(this.sound);
},
// 하지만 화살표 함수는 작동 안한다!!!
say: () => {
console.log(this.sound);
}
// TypeError: Cannot read property 'sound' of undefiend. 오류 출력한다.
// 즉, this 객체를 읽지 못한다.
// 화살표 함수는 this를 자기가 속해 있는 곳으로 연결을 하지 않기 때문이다.
};
dog.say();
// 멍멍! 출력.
const cat = {
name: '야옹이',
sound: '야옹~'
};
cat.say = dog.say;
cat.say();
// 야옹~ 출력.
const catSay = cat.say;
catSay();
// TypeError: Cannot read property 'sound' of undefiend. 오류 출력한다.
// 화살표 함수와 마찬가지로 catSay는 아무것도 연결되어 있지 않기때문에
// 즉, this가 연결된 곳이 없기 때문에 에러가 발생한다.
// 함수를 바깥으로 꺼내서 사용할 경우에는 this의 관계가 사라진다는 것을 알 수 있다.
cat.say = dog.say; 코드를 통해 dog 객체 안에 있는 함수를 cat의 say라는 함수 이름으로 넣어줄 수 있습니다.
그래서 야옹~을 출력하게 됩니다.
하지만 그 다음이 좀 헷갈립니다. cat.say에는 console.log(this.sound);가 들어가 있습니다. 근데 이것을
catSay라는 변수에 넣고 catSay()를 호출 시키면 위와 같은 타입 에러가 발생합니다.
cat.say()를 호출하면 "야옹~"이 잘 출력되는데 왜 catSay()를 호출하면 에러가 뜰까요?
그 이유는 this의 연결 여부 때문입니다. cat.say()를 호출할 경우에는 그 안에 들어가 있는 this.sound 코드에서 this는 자기 자신인 객체 cat을 연결하게 되고, 그에 따라 cat 객체안에 있는 sound를 호출하게 됩니다.
하지만 const catSay = cat.say; 를 넣어준다고 해서 catSay 변수 안에 있는 this.sound의 this가 자연스럽게 cat 객체와 연결이 될까요? 아닙니다.
여기에서의 this는 undefined를 반환하게 됩니다. this.sound의 this는 아무것도 연결이 되지 않습니다. 함수를 바깥으로 꺼내서 사용할 경우에는 this의 관계가 사라지게 되기 때문입니다. 즉, this는 연결된 곳이 없기 때문에 에러를 발생합니다.
객체 생성자 (prototype, new 키워드)
객체 생성자는 new 키워드를 이용해 선언합니다.
객체를 생성할 때는 변수명의 맨 앞글자를 대문자로 합니다.
아래 코드는 함수로 객체를 생성할 때의 기본적인 예시로써 비효율적인 코드입니다.
// 객채를 생성할 때는 변수명의 맨 앞글자는 대문자로 한다.
function Animal(type, name, sound) {
this.type = type;
this.name = name;
this.sound = sound;
this.say = function() {
console.log(this.sound);
}
}
const dog = new Animal('개', '멍멍이', '멍멍');
const cat = new Animal('고양이', '야옹이', '야옹');
dog.say(); // "멍멍" 출력
cat.say(); // "야옹" 출력
// 위의 코드는 비효율적인 이유가 새로운 Animal 객체를 생성할 때마다
// 똑같은 내용의 새로운 함수인 this.say 함수를 매 번 만들어 주고 있다는 것이다.
아래 코드는 prototype을 적용한 코드입니다.
// 객채를 생성할 때는 변수명의 맨 앞글자는 대문자로 한다.
function Animal(type, name, sound) {
this.type = type;
this.name = name;
this.sound = sound;
}
Animal.prototype.say = function() {
console.log(this.sound);
}
/*
위의 prototype 코드는 아래 코드와 같은 역할을 한다.
function say() {
console.log(this.sound);
}
dog.say = say;
cat.say = say;
즉, 모든 say 함수를 dog, cat 객체에 넣어준 것이다.
*/
dog.say(); // "멍멍" 출력
cat.say(); // "야옹" 출력
// prototype은 선언해줌으로써 함수는 한번만 만들어 주고
// 새로운 객체가 들어올때마다 바인딩 시켜주는 역할은 한다. (재사용)
ES6 Class
Class는 객체 생성자와 Prototype을 좀 더 쉽게 사용하기 위해서 만들어진 문법이다.
Class 내부에 함수를 만들게 되면 자동으로 그 함수는 prototype으로 등록이 됩니다.
class Animal {
// 생성자
constructor(type, name, sound) {
this.type = type;
this.name = name;
this.sound = sound;
}
say() {
console.log(this.sound);
}
}
const dog1 = new Animal('개', '멍멍이', '멍멍');
const cat1 = new Animal('고양이', '야옹이', '야옹');
dog1.say(); // "멍멍" 출력.
cat1.say(); // "야옹" 출력.
// class 내부에 함수를 만들게 되면 자동으로 그 함수는 prototype으로 등록이 된다.
console.log(Animal.prototype.say);
// say()함수에 대한 정보가 출력된다.
// class 문법은 상속을 해야하는 상황에서 더 쉽게 할 수 있다.
class Dog extends Animal {
/*
기존 Aniamal 객체에서 쓰는 constructor를 덮어 쓴다.
이 과정에서 super 키워드를 이용하여 Animal이 가지고 있는 constructor를
먼저 호출하고 나서 자신이 해야할 일을 처리할 수 있다.
*/
constructor(name, sound) {
super('개', name, sound);
}
}
class Cat extends Animal {
constructor(name, sound) {
super('고양이', name, sound);
}
}
const dog2 = new Dog('멍멍이', '멍멍');
const cat2 = new Cat('고양이', '야옹');
dog2.say(); // "멍멍" 출력.
cat2.say(); // "야옹" 출력.
Class 문법은 상속을 해야하는 상황에서 더 쉽게 할 수 있습니다.
Super키워드를 이용하여 부모 객체가 가지고 있는 constructor를 먼저 호출할 수 있습니다.
강의 링크
프론트엔드 개발 올인원 패키지 with React Online. | 패스트캠퍼스 (fastcampus.co.kr)
'공부 || 정리 > JavaScript' 카테고리의 다른 글
댓글
이 글 공유하기
다른 글
-
[JavaScript] 함수의 기본 파라미터, 조건문 더 스마트하게 쓰기, 비구조화 할당
[JavaScript] 함수의 기본 파라미터, 조건문 더 스마트하게 쓰기, 비구조화 할당
2021.03.02 -
[JavaScript] 삼항연산자, Truthy와 Falsy, 단축 평가 논리 계산법
[JavaScript] 삼항연산자, Truthy와 Falsy, 단축 평가 논리 계산법
2021.03.01 -
[패스트캠퍼스] 프론트엔드 인강 환급 챌린지(3) JavaScript - 배열 내장함수 shift, pop, push, unshift, reduce
[패스트캠퍼스] 프론트엔드 인강 환급 챌린지(3) JavaScript - 배열 내장함수 shift, pop, push, unshift, reduce
2021.02.23 -
[패스트캠퍼스] 프론트엔드 인강 환급 챌린지(2) JavaScript - 배열 내장함수 forEach, map, filter 등등
[패스트캠퍼스] 프론트엔드 인강 환급 챌린지(2) JavaScript - 배열 내장함수 forEach, map, filter 등등
2021.02.19