[코딩애플] JavaScript ES6 강의 정리 (Part2 9강 ~ 10강)

이언덕·2024년 7월 16일

코딩애플

목록 보기
36/37
post-thumbnail

9강 / constructor, prototype 연습문제 4개

0. object 자료 여러개를 만들고 싶습니다.

하드코딩해봤다.

let student1 = { name : 'Kim', age : 20 }
let student2 = { name : 'Park', age : 21 }
let student3 = { name : 'Lee', age : 22 }

하드코딩해서 3개를 만들긴 했는데 앞으로 만들일이 더 많이 생길 것 같아서 constructor를 제작하려고 한다.

constructor문법을 사용해서 위의 object와 똑같은 object 3개를 한번 뽑아보십시오.

  • 여기에 student1.sayHi()라고 사용하면 "안녕 나는 Kim이야" 라는 글자가 콘솔창에 나오도록 sayHi()라는 함수도 constructor 안에 추가해보자.

풀이

1. constructor 함수 만들기

function Machine() {
  this.name = ?;
  this.age = ?;
}

let student1 = new Machine();
let student2 = new Machine();
let student3 = new Machine();

constructor에 대한 함수를 만들어주었고 student1, student2, student3에는 각각 Machine의 속성인 nameage를 갖게 된다.


2. 파라미터로 각 이름과 나이 넣기

각 학생마다 이름과 나이가 다르니 파라미터로 나누어보자

function Machine(personName, personAge) {
  this.name = personName;
  this.age = personAge;
}

let student1 = new Machine("Kim", 20);
let student2 = new Machine("Park", 21);
let student3 = new Machine("Lee", 22);

위와같이 파라미터를 통해 각 이름과 나이를 저장시켰다. 한번 출력해보자

console.log(student1);
console.log(student2);
console.log(student3);


각 학생의 이름과 나이가 들어간 것을 볼 수 있다.


3. student1.sayHi()라고 사용하면 "안녕 나는 Kim이야" 라는 글자가 콘솔창에 나오도록 sayHi()라는 함수도 constructor 안에 추가하기

function Machine(personName, personAge) {
  this.name = personName;
  this.age = personAge;
  this.sayHi = function () {
    console.log(`안녕 나는 ${this.name}이야`);
  };
}

let student1 = new Machine("Kim", 20);
let student2 = new Machine("Park", 21);
let student3 = new Machine("Lee", 22);

student1.sayHi();

위 1, 2, 3 풀이 방법이 기억이 나지 않는다면 6강 (객체지향1. Object 생성기계인 constructor를 만들어 써보자)를 다시 보고 오자!



1. 다음 코드의 출력 결과는 무엇일까?

function Parent(){
  this.name = 'Kim';
}
let a = new Parent();

a.__proto__.name = 'Park';
console.log(a.name)

풀이


'Kim' 이다.

이유

    1. 첫 4줄에 의해서 a = { name : 'Kim' } 이 된다. (new Parent() 이 코드로 인해 a에 객체가 생성됨!)
    1. a.__proto__.name = 'Park'; 이건 부모 prototype{ name : 'Park' } 이걸 추가하라는 뜻이다.
    1. 그럼 이제 console.log(a.name) 이라고 사용했을 때
      내가 직접 가지고 있는 { name : 'Kim' } 이걸 우선 출력해준다.

Park이 안나오는 이유

aname 속성이 a.__proto__.name (즉, Parent.prototype.name)보다 우선하기 때문이다.



2. 함수가 안들어간다

위에 0번 문제에서 Student라는 부모에 sayHi라는 함수를 하나 추가하라고 했다.
그래서 sayHi()라고 사용하면 "안녕 나는 ~~이야" 라고 내 이름을 출력해주는 함수를 prototype에 추가했다.
하단처럼 만들었는데 의도한 대로 이름이 출력되지 않고 있다.
원인은 무엇일까?

function Student(name, age){
  this.name = name;
  this.age = age;
}

Student.prototype.sayHi = () => {
    console.log('안녕 나는 ' + this.name + '이야');
  }
let student1 = new Student('Kim', 20);

student1.sayHi();//왜 이 코드가 제대로 안나오죠?

풀이

sayHi() 라는 함수를 prototype에 추가할 때 arrow function을 사용했다.
결론부터 말하자면 arrow function은 그냥 일반 function 대체품이아니다.
arrow functionthis를 바깥에 있는 this를 그대로 사용하고 싶을 때 쓰는 함수라고 했었다.
그런데 sayHi() 함수를 만들 때 arrow function을 사용해서
내부에 있던 this라는 값이 이상해진 것이었다.


Student.prototype.sayHi = () => {
    console.log(this);
}

sayHi 함수에 그냥 this 하나만 출력해보면 window 같은게 출력될 것이다. (strict mode에선 undefined)

이전 Part1 5강의내용에 따르면 arrow function을 사용하면 그냥 바깥 아무데나 있던 값을 가져와서 사용한다.
바깥 this 값은 window이며,
window를 그대로 저기 함수 안에다가 적용했기 때문이다.
그래서 this가 이상해서 그랬던 문제였다.

this 잠깐 복습하자면
함수안에서 this 키워드의 뜻은 매번 재정의된다.
object안에 들어있는 함수안에 있는 this는 함수를 부른 object가 된다고 했다.
하지만 arrow function의 경우 함수 안에서 this 뜻이 재정의되지 않고 바깥에 있던 this를 사용한다.

var objTest = {
  sayHi : () => { console.log(this) }
}
objTest.sayHi();

▲ 그래서 위 코드의 this
object 그런게 아니라 window가 출력된다.
문제에 나온 예제도 위랑 같은 식이다.



기억이 나질 않는다면 Part1 5강을 참고하자!



3. 모든 array에 적용할 수 있는 함수를 직접 새로 만들려면 어떻게 해야할까?

모든 array에 붙일 수 있는,
array 내에 있는 3이라는 값을 제거해주는 유용한 함수를 하나 만들고 싶다.

let arr = [1,2,3];
arr.remove3();

console.log(arr);//[1,2]

이렇게 array뒤에 붙이기만 하면 array 내의 3이라는 모든 숫자 자료들이 삭제된다.
이름은 remove3() 이라고 하겠다.
remove3()함수는 어떻게, 어디에 만들어야 모든 array에 쓸 수 있을까?


풀이

일단 모든 arraypop(), sort(), push() 이런 함수를 붙일 수 있는 이유는 무엇이였을까?
모든 array 자료형은 부모가 Array로 부터 new Array() 이런 식으로 만들어지기 때문에
Array라는 부모의 prototype에 있는 함수들을 자유롭게 가져다 쓸 수 있어서 그렇다.

그럼 Arrayprototyperemove3라는 함수를 하나 추가해주면 되는게 아닐까?

Array.prototype.remove3 = function(){
  this 에서 3을 찾아서 제거해주세요
}

이렇게 코드를 짜면 될 것 같다.


위의 코드에서의 this라는 키워드는 현재 remove3이라는 함수를 작동시키는 object (여기서는 array) 라는 뜻이다.
그럼 this라는 array에서 3을 제거하는 코드는 어떻게 짤까?
나는 this라는 array 안에 있는 데이터를 하나하나 출력하면서 3과 비교하려고 반복문을 썼다.

Array.prototype.remove3 = function(){
  for (var i = 0; i < this.length; i++) {
    if ( this[i] === 3 ) {
      this.splice(i,1);
    }
  }
};

var arr = [1,2,3,4];
arr.remove3();

console.log(arr);//[1,2,4]

위 코드를 설명하자면 remove3()함수는

    1. this라는 array의 길이만큼 반복문을 돌리는데, 돌리는 과정에서 this[i] 라고 쓰면서 this 안에 있는 모든 데이터를 출력해봅니다.
    1. 만약에 this[i]3이면
    1. this라는 array에서 i번째 자료를 제거해주세요

라고 썼다. (splice 라는 함수는 array안에 뭘 제거할 때 가끔쓴다.)

10강 / (간만에 쉬운거) ES5방식으로 쉽게 구현하는 상속기능

Object.create() 사용하기

Object.create(부모object);
이렇게 사용하면 이 자리에 object 자료형 하나가 남는다.
그리고 소괄호 안에 적은 부모object유전자(prototype)가 되는 것이다.

한번 예를 들어보자.

var parent = { name : 'Kim', age : 50 };
var child = Object.create(parent);

console.log(child.age);//50나옴

이렇게 쓴다는 소리이다.


그럼 child이라는 objectparentprototype으로 두게 된다.
그럼 child.name 해도 'Kim'이 출력되고, child.age 해도 50이 출력된다.
자식이 성공적으로 부모 속성들을 상속했다.



그럼 자식이 age를 바꾸고 싶으면 어떻게 할까?

age가 50이라고 한다.
이걸 20살로 바꿔보자.

var parent = { name : 'Kim', age : 50 };
var child = Object.create(parent);
child.age  = 20;

console.log(child.age);//20 나옴

그냥 child이라는 objectage : 20 이라는 값을 부여했을 뿐이다.
그럼 이제 child.age 할 때마다 20이 출력된다.

Q. 부모로부터 상속받은 50이라는 age가 출력되지 않는 이유는 뭘까?

왜냐면 자바스크립트 object 자료형에서 특정 자료를 꺼낼 때 묻는 순서가 있다고 배웠었다.
child.age를 꺼내주세요~ 라고 하면

    1. child이라는 object가 직접 age를 가지고 있으면 그거 출력
    1. 없으면 child의 부모 prototype을 뒤져서 age가 거기 있으면 그거 출력
    1. 거기도 없으면 부모의 부모 prototype을 뒤져서..
      이런 순서로 age를 출력한다.
      그래서 지금 child은 20이 나오는 것이다.


손자도 쉽게 만들 수 있다.

그니까 자식의 자식도 쉽게 만들 수 있다는 소리이다.
부모가 가진 속성, 자식이 가진 속성을 전부 물려받는 손자를 만들어보자.

var parent = { name : 'Kim', age : 50 };
var child = Object.create(parent);
child.age  = 20;

var grandson = Object.create(child);

console.log(grandson.age);

grandson를 만들었다.
grandson는 자식과 부모가 가진 속성들을 전부 물려받는 상태이다.

그럼 grandson.age하면 무엇이 나올까?
20이 출력된다.

이게 상속의 상속을 받는 방법이다.
값 추가도 object 다루듯이 하면 된다.
함수 추가하는 것도 그냥 등호로 넣으면 된다.
하지만 요즘 개발자들은 있어보이게 class, 그리고 extends 문법을 이용해서 상속의 상속기능을 만들어낸다.


▲ 특히 옛날 리액트 문법으로 짜여진 코드볼 때 extends 문법 가끔 구경가능하다.

0개의 댓글