클래스의 속성중 하나인 private속성은 class안에서만 사용하는 값이므로 외부에서 수정할 수 없고

확인도 할 수 없다.

 

때문에 상황에 따라서 속성을 읽고 쓸 수 있는 메소드를 만드는데 이것이 게터와 세터라고 할 수 있다.

 

여기서 게터는 getter라는 이름처럼 속성값을 확인할 때 사용하고

세터는 setter라는 이름처럼 속성값을 지정해줄 때 사용한다.

 

아래 코드를 보자

  // 정사각형 클래스
  class Square {
    #length							//#length는 private

    constructor (length) {					//클래스의 파라미터로 length 추가
      this.length = length
    }

    //아래 코드는 위의 길이값을 바탕으로 둘레, 한 변의 길이, 넓이를 계산하는 코드
    get length () {return this.#length}
    get perimeter () {return this.#length * 4}
    get area () {return this.#length * this.#length}
    
    //아래 코드는 set을 사용
    set length (length) {
      if (length <= 0) {
        throw '길이는 0보다 커야 합니다.'
      }
      this.#length = length
    }
  }

  // 클래스 사용하기
  const squareA = new Square(10)
  console.log(`한 변의 길이: ${squareA.length}`)
  console.log(`둘레: ${squareA.perimeter}`)
  console.log(`넓이: ${squareA.area}`)

  // 예외 발생시키기
  const squareB = new Square(-10)
  
  // 실행결과
  // 한 변의 길이: 10
  // 둘레: 40
  // 넓이: 100
  // 에러 하나

자, 여기서 length는 private다.

 

아래 get을 사용한 코드 3줄이 있는데, 이것은 private 값인 length를 이리저리 조작해서 얻은 값을 불러오게 하는 코드다

실제로 아래 '클래스 사용하기' 줄을 보면 결과적으로, private값을 가져온 것을 알 수 있다.

 

아래 set을 사용한 코드를 보면 조건문의 경우는 그냥 에러걸러내는 용이니 넘어가고 그 다음줄을 보면

this.#length = length가 있다.

즉 private 값인 #length에 외부에서 가져온 파라미터 값인 length를 넣는다는 뜻이다.

 

결과적으로 외부에서 내부 private에 간섭을 한것이라고 볼 수 있는데

 

어쨌든 값 변화는 클래스 내부에서 일어난 것이기 때문에 문제는 없다.

 

 

정리

밖과 절대로 소통하지 않는 방구석 폐인에게 외부인이 편지를 써봤자 그 폐인은 우체통을 결코 확인하지 않을 것이다.

때문에 그와 함께 사는 가족들에게 직접 편지를 건네고

그 가족을 통해 폐인에게 편지가 도착하는 것이다.

 

여기서 방구석 폐인은 private라고 할 수 있고

그와 소통해주는 가족이 게터와 세터라고 할 수 있고

외부인은 그 private에 접근하려고 하는 외부인자들이라고 할 수 있다.

 

다만 주의해야할 것이

코딩의 편의성을 위해 모든 private에 게터와 세터를 사용하려는 경우가 있을 수 있다는 것이다.

하지만 그렇게 했다간 대체 왜 private 속성을 사용하겠는가

만약 값을 함부로 보여줘선 안 된다고 한다면 게터와 세터의 사용을 지양해야 할 것이다.

 

마지막으로 게터와 세터 코드의 간결한 코드를 작성하고 끝내겠다.

 

class 클래스 이름{
	get 이름() {return 값}
    set 이름(value) {}
}

 

 

 

1. 클래스?

C언어를 제외한 대부분의 프로그래밍 언어는 객체지향 패러다임을 기반으로 만들어 졌다.

 

객체지향이란 말 그대로 객체를 우선적으로 생각해서 프로그램을 만든다는 방법론이다.

 

객체지향 말고 다른게 뭐가 있냐? 라는 생각도 들법한데, 바로 절차 지향이다.

 

 

이 두가지는 어떻게 다른가??

 

절차지향은 턴제 시뮬레이션 게임이다.

순서가 정해져 있고, 그 순서가 끝나기 전에 다른 이들이 행동할 수 없다.

객체지향은 

 

 

자, 여기 프로브와 드론이 영혼의 대결을 펼치고 있다.

프로브와 드론의 체력은 20으로 하고 각각 5의 공격력을 가지고 있으며 프로브가 선공을 가진다라고 정의해보자

이걸 절차지향으로 나타내면 다음과 같다.

프로브와 드론의 대결! 프로브 체력 20! 공격력 5!
드론 체력 20! 공격력 5!
프로브의 선공! 드론의 남은체력 15!
드론의 반격! 프로브의 남은체력 15!
프로브의 공격! 드론의 남은체력 10!
드론의 공격! 프로브의 남은체력 10!
프로브의 공격! 드론의 남은체력 5!
드론의 공격! 프로브의 남은체력 5!
프로브의 선공! 드론의 남은체력 0!

프로브가 승리했다!

 

그럼 이걸 객체지향으로 표현한다면??

우리가 스타크래프트로 두 유닛을 붙여놓은거랑 비슷하다.

선공의 개념을 정해줄 필요가 없으며

각 객체가 서로 독립적이고 따로 행동하며

프로브와 드론은 굳이 순서에 얽매이지 않고 유기적으로 행동할 수 있다.

 

2. 추상화?

 

위의 프로브를 보자,

실제로, 프로브는 체력 20, 보호막 20, 공격력 5, 방어력 0, 크기는 소형 이라는 요소를 가진 객체다.

만약 프로브가 실제로 존재한다면 요소는 이게 끝이 아닐 것이다.

아마 질량과 중량, 재질, 각 부분별 길이부터 구성하고 있는 원소의 종류와 수와 상태까지,

열거하자면 그야말로 끝도 없을 것이다.

 

하지만 게임에서 구현할 때는 이런건 전부 필요 없다.

즉, 필요한 요소만 가지고 객체를 표현한 것이 바로 추상화라고 할 수 있다.

 

 

프로토스에겐 프로브만 있는 것이 아니다.

위와 같이 다양한 유닛이 있다.

이것들을 관리하기 위해서 필요한 공통사항을 추출하는데 이를 추상화라고 한다.

 

공통사항으론 다양한 것이 존재한다.

체력, 방어력, 타입, 속성, 공격여부, 지상유닛인지 공중유닛인지에 대한 구분, 건물인지 아닌지에 대한 구분 등이 있을 것이다.

 

이를 코드로 작성해보면 얼추 이렇게 나온다.

const unit []
unit.push({이름: 프로브, 공격력: 5, 방어력: 0, 체력 20, 보호막: 20})
unit.push({이름: 질럿, 공격력: 16, 방어력: 1, 체력 100, 보호막: 60})
unit.push({이름: 드라군, 공격력: 20, 방어력: 1, 체력 100, 보호막: 80})

이하 생략...

 

우리는 이러한 데이터를 가지고 입맛에 맞게 조리할 수 있다.

공격력부터 보호막까지 더한 수치를 전투력이라고 정의해보자

 

for (const p of unit){
	const sum = p.공격력 + p.방어력 + p.체력 + p.보호막
    output = sum
    }
console.log(output)

이걸 실행하면 각 수치를 더한 값을 얻을 수 있다.

 

물론 단순히 더하는 것 뿐만 아니라 지금까지 배운 것을 종합하면

 

 

 

3. 클래스 선언

다시 클래스로 넘어와보자

클래스를 선언해보자

class 클래스의 이름{
}

'클래스의 이름'이라는 클래스를 만들었고 이것을 복사해보자

 

new 클래스의 이름

자, 클래스의 이름의 인스턴스를 만들었다.

이게 뭔 내용인가 이해하기 힘들 수 있는데, 아까 그 프로브를 인용하면 다음 같다.

 

 

자, 맵상에 여러마리의 프로브가 있다.

이 프로브들은 처음 생산될때는 서로 같은 값을 가지지만 이게 항상 동일하지는 않다.

누군가는 공격을 당했을 것이고

누군가는 방어력 업그래이드를 했을 것이다.

 

즉, 클래스란 기초가 되어주는 원본이고

인스턴스란 그 원본을 복사해낸 것이다.

인스턴스가 가지고 있는 값이 변하여도 클래스가 가진 값은 변하지 않는다.

수많은 프로브들 가운데 누가 두들겨 맞았다고 해서

앞으로 생산될 다른 프로브들 까지 두들겨 맞은체로 태어나지는 않을태니 말이다.

 

하지만 클래스가 바뀌어버린다면

이후로 생성될 인스턴스의 값들도 바뀌어버린다.

원본이 수정되었으니 그 이후에 만들어진 사본들도 바뀐체로 태어나는 것이다.

 

 

4. 생성자

클래스 안에 새로운  것을 만들어주는 역할을 한다.

 

class Unit {
	constructor(이름, 공격, 방어, 체력){
    this.이름 = 이름
    this.공격 = 공격
    this.방어 = 방어
    this.체력 = 체력
    }
}

const unit = []
unit.push(new Unit('신캐A', 16, 2, 20))
unit.push(new Unit('신캐B', 216, 12, 4120))
unit.push(new Unit('신캐C', 600, 2, 20000))

 

만약에 스타크래프트에 새로운 유닛이 생성된다고 가정해보자

설령 새로운 유닛이라 할지라도 기존의 유닛들과 공통점이 있을 것이다.

(예를 들면, 위 처럼 이름을 가지고 있다던지 체력을 가지고 있다던지/)

그 공통점을 바탕으로 새로운 유닛을 만들고 정의할 수 있다.

 

그 역할을 해주는 것이 바로 생성자라고 할 수 있다.

 

5. 메소드

클래스 안에 함수를 추가해주는 것이라 할 수 있다.

 

예를들어, 신캐릭터의 가격이 그 캐릭터의 모든 스텟을 합친것과 같다고 가정해보자

 

 

class Unit {
    constructor(이름, 공격, 방어, 체력){
    this.이름 = 이름
    this.공격 = 공격
    this.방어 = 방어
    this.체력 = 체력
    }
    
    price() {
    	return this.공격 + this.방어 + this체력
    }
}

const unit = []
unit.push(new Unit('신캐A', 16, 2, 20))
unit.push(new Unit('신캐B', 216, 12, 4120))
unit.push(new Unit('신캐C', 600, 2, 20000))

 

이렇게 하면 새로 정의한 신캐 A,B,C의 가격은 각각 38, 4348, 20602가 될 것이다.

 

여기서 가격을 계산해준 price()가 메소드가 된다.

사실 프리티어는 자바스크립트 뿐만 아니라 프로그래밍 전반에도 비슷한 개념이 있을거라 생각한다.

하지만 일단은 여기에 적도록 한다.

 

 

1. 쉽게 말해 코드를 작성하는 스타일...

코드를 작성하다보면 들여쓰기가 자동으로 되는 것을 알 수 있다.

그런데 이러한 들여쓰기 조차 누구는 Spacebar를 여러번 누르고 누구는 Tap을 한 번 누른다.

 

또한 중괄호를 쓰는 구문을 보면, 누구는 짧은 구문도 시작괄호와 닫는 괄호가 각각 한 줄씩 차지하는 반면

누구는 그딴거 없이 한 줄로 심플하게 끝내기도 한다.

 

그림을 그리는 사람에게 그림체가 있고 글을 쓰는 사람에게 글씨체가 있지만

단순한 모양을 넘어서, 그림 그리는 사람들에겐 주로 그리는 장르나 좋아하는 요소가 있기 마련이고

글을 쓰는 사람들 또한 글씨체를 넘어서, 추구하는 화술이 있다.

 

프로그래머들도 마찬가지고 이 스타일로 인한 가독성 때문에 서로 엄청나게 싸웠다고 한다.

 

 

2. 그래서, 프리티어란?

코드 서식 관리 도구 라고 할 수 있다.

 

https://prettier.io/playground/

 

위 사이트에서 사용해 볼 수 있다.

 

프리티어를 다운 받아서 본인이 사용하고 있는 코딩 프로그램에 적용시킬 수 있다.

또한 프리티어가 기본적으로 제공하는 규칙이 있으나 이 규칙을 본인의 입맛에 맞게 바꿀 수 있다.

 

만약 본인이 VS-Code를 사용한다면 터미널에 다음 명령을 입력하여 설치할 수 있다.

npm i prettier -D

프리티어는 서비스 구동에 필요한 모듈이 아니니 -D로 설치한다.

그리고 나서 app.js 파일이 있는 폴더에 .prettierrc.js 라는 파일을 만들고 (앞에 점 주의) 아래의 내용을 넣는다.

 

{
  "printWidth": 80, //  줄 바꿈 할 폭 길이
  "tabWidth": 2, // 탭 너비 
  "singleQuote": true, // single 쿼테이션 사용 여부
  "trailingComma": "all", // 여러 줄을 사용할 때, 후행 콤마 사용 방식
  "jsxBracketSameLine": false, // JSX의 마지막 `>`를 다음 줄로 내릴지 여부
}

 

그리고 package.json 파일을 보면 scripts 라는 항목이 있는데 그 항목의 하위에다가 다음을 넣어주자

"prettify": "prettier --write *.js **/*.js"

 

참고로 위 코드를 넣으면 대략 다음처럼 나와야 한다

{
    "name": "프로젝트 이름",
    "version": "1.0.0",
    "scripts": {
        "start": "node app.js",
        "prettify": "prettier --write *.js **/*.js"
    },
... 생략
}

 

이후 터미널에 다음을 입력하여 프리티어를 실행한다.

npm run prettify

 

 

3. 프리티어 각 항목의 규칙

아래 코드를 설명하는 형식으로 진행해 보겠다

module.exports = {
  trailingComma: 'es5',
  tabWidth: 2,
  semi: true,
  singleQuote: true,
  arrowParens: 'always',
};

 

1. tarilingComma란 바로 위 코드의 끝부분 처럼 모든 항목에 쉼표를 넣을 것인가에 대한 여부다.

물론 쉼표는 꼭 넣어줘야 하지만 마지막 항목에는 넣어줄 필요가 없는데 이것을 설정하는 것이라고 생각하면 된다.

es5라는 값은 ES5버전에서 허용되는 부분까지만 콤마를 붙인다는 뜻이다.

none이라는 값은 쓸모없다고 판단되는 모든 콤마를 제거합니다.

all은 반대로 바로 위 코드 처럼 끝에도 넣어주는 것이다. 그러나 그런 형태를 지원하지 않는 경우가 있기 때문에 비추천한다.

 

2. tabwidth란 들여쓰기 간격을 뜻한다.

 

3. semi란 코드 뒤에 ;를 붙일 것인가에 대한 규칙이다. 자바스크립트는 세미콜론이 없어도 상관없지만, 몇몇 언어는 이게 없으면 코드 자체가 못 읽히는 현상이 발생하곤 한다.

때문에 가급적이면 true로 해 놓기를 권장한다.

 

4. singleQuote란 문자열을 입력할 때 쌍따옴표를 쓸 것인가, 외 따옴표를 쓸 것인가를 결정한다.

뭘로 해도 상관없지만 외따옴표(true)를 권장한다.

 

5.arrawParens란 함수의 파라미터에서 괄호를 항상 넣을 것인가 말 것인가를 정하는 규칙이다.

이 또한 always로 항상 해두는 것을 권장한다.

 

1. 예외란?

초간단하게 그냥 에러다.

그렇다면 예외처리란?

말그대로 에러가 발생했을때 어떻게 할 것인가를 나타낸다.

 

프로그래밍이란 에러와의 싸움이다.

오죽하면 프로그래머의 실력은 경험한 에러의 양과 비례한다고 하겠는가

나도 지금까지 수 많은 에러를 경험했다.

그러니, 이번에 분명히 짚고 넘어가자

 

 

예외처리란 전쟁무기와도 비슷한것 같다.

그 누구도 쓸일이 없기를 바라며 실제로 쓸일이 없었다 한들 방심하고 방치해선 안 되는 점에서 말이다.

 

1-1 구문오류

쉽게말해 나같은 실력이 부족한 병아리 개발자가 오타를 섰거나 괄호 갯수를 잘 못 입력해서 아예 실행조차 안 되는 경우를 말한다.

사소한 오타 하나 때문에 웹 브라우저가 코드를 읽지 못하는 경우는 아주 흔하다.

이런 경우 다음과 같은 에러가 발생한다.

 

예를 들어, console.log()의 괄호를 닫지 않으면 다음과 같이 발생한다.

D:\VSCode-prac\연습용\app.js:1
console.log(


SyntaxError: Unexpected end of input

 

이러한 류의 오류는 보통 어디서 못 읽었는지를 알려주기 때문에 해결하기 쉬운 편이다.

당장 위 코드만해도 D 드라이브의 VSCode-prac 폴더의 연습용 폴더의 app.js 파일의 1번째 줄에서 에러가 났으며

그 에러가 난 코드를 정확하게 보여주고 있다.

 

1-2 예외

실행중 발생하는 에러로 런타임 오류라고 한다.

이번엔 console.log()를 console.rog()로 잘 못 입력해 보겠다.

PS D:\VSCode-prac\연습용> node app
D:\VSCode-prac\연습용\app.js:1
console.rog()
        ^

TypeError: console.rog is not a function

 

이번에도 에러가 난 부분을 정확하게 짚어주고 있다.

console에는 rog라는 메소드가 없다.

때문에 에러가 발생한다.

다만 아까와는 다른 큰 차이점이 있다.

 

그 차이점을 알아보기 위해 다음을 각각출력해 보겠다

console.log("aaaa")
console.rog()
console.log("aaaa")
console.log(

 

이결 출력한 결과는 다음과 같다.

PS D:\VSCode-prac\연습용> node app
aaaa
D:\VSCode-prac\연습용\app.js:2
console.rog()
        ^

TypeError: console.rog is not a function
D:\VSCode-prac\연습용\app.js:2
console.log(


SyntaxError: Unexpected end of input

차이점을 찾았는가?

메소드를 잘 못 입력한 경우에는 aaaa가 출력되는 것을 알 수 있다.

반면 괄호를 입력하지 않은 경우에는 어떤것도 출력되지 않는다.

 

즉 구문오류와는 달리 예외란 문제가 발생한 부분 전까지는 전부 실행된다는 차이점이 있다.

 

2. 기본 예외 처리

조건문을 사용해서 예외를 발생하지 않게 하는 것을 기본 예외처리라고 한다.

예를들어, 특정 값을 추출했는데 if문을 사용해 이 값이 존재하는 값인지 아닌지를 분별해낼 수 있다.

물론 if 문을 쓰지 않고 없는 값을 출력했다고 해서 코드가 멈춰버릴만큼 자바스크립트가 융통성이 떨어지는 언어는 아니다.

다만 그렇다고 해서 예외처리를 해주지 않으면 이것이 나중에 문제를 일으킬 수 있으며

추후에 문제가 발생했을 때 문제를 파악하기 어려울 수도 있다.

때문에 문제가 예상되는 부분에는 조건문으로 예외처리를 해주는 것이 좋다.

 

 

3. 고급 예외 처리

try, catch, finally 문을 사용한 예외처리를 고급 예외처리라고 한다.

이것을 살펴보면 다음과 같다.

 

try{	
			//try 구역
} catch (exception){
			//catch 구역
} finally {
			//finally 구역
}

보시다시피 3개의 구역으로 나뉜다.

 

try: 에러가 발생할 수 있다고 여겨지는 코드들을 여기에 넣는다.

이곳에 들어간 코드는 위에서부터 순차적으로 실행된다.

 

catch: try구역을 실행하던 도중 에러가 발생할 경우, try를 멈춰버리고 이곳으로 넘어간다.

만약 에러가 발생하지 않는다면 이 구역은 실행되지 않는다.

 

finally: try 구역에서 에러가 발생했든 하지 않았든 최종적으로 실행되는 부분이다.

만약 try 구역에서 에러가 발생했다면 catch로 넘어와서 catch를 모두 실행한 다음 finally를 실행한다.

만약 try 구역에서 에러가 발생하지 않았다면 try 구문을 종료하고 바로 finally로 넘어온다.

단, finally는 필수 구역이 아니다. 없어도 상관없는 부분이다.

 

 

3-1. finally는 언제 쓰는가?

 

finally구문은 언제 써야하는가? 라고 생각할 수 있는데

주로 try구문 안에 return이나 continue, break와 같은 함수를 탈출하는 구문을 사용한다면 쓸 수 있다.

이러한 함수를 끝내는 명령어와 만나면 그걸 실행하기 직전에 finally를 실행한다.

try{	
    console.log("aaa")
    return
    console.log("bbb")
} catch (exception){
    console.log("ccc")
} finally {
    console.log("ddd")
}

예를 들어 위의 코드를 보자

aaa를 출력하고 return을 만난다.

그럼 진짜로 return을 하기 전에 finally를 먼저 실행한다.

그리고 진짜로 retrun을 한다.

즉 출력 결과는 아래와 같다.

aaa
ddd

 

 

4. 마지막

에러를 없앨 수는 없을까?

이쯤되면 나같은 병아리 개발자는 에러가 예상된다면 여러가지 시도를 통해 에러가 발생하지 않게 하면 되지 않느냐고 생각할 수 있다.

그러나 에러라는 것은 그렇게 단순한 것만 있는게 아니다.

예를 들면 로그인을 할 때 아이디나 비밀번호를 잘 못 입력한 것도 일종의 에러라고 할 수 있기 때문이다.

즉, 사용자가 로그인 할 때, 아이디나 비밀번호를 잘 못 입력하는 경우가 발생할 경우를 대비해 저런 구문을 사용하는 것이라고도 할 수 있다.

 

또한 예외처리는 이것만 있는게 아니다.

예외처리 고급에 관한 부분은 다음에 이 게시글의 내용을 추가하거나 아니면 새로운 게시글을 작성하도록 하겠다.

1.호이스팅이란?

var라는 키워드와 연관이 있다.

 

앞서 var는 분명 문제아라고 했었다.

다음 두가지를 보자

 

console.log(name);
var name = 'Tarel'
console.log(name);
let name = 'Tarel'

 

두 코드는 별 차이는 없고 let이냐 var냐 정도의 차이다

그러나 결과는 다르다 var는 undefined가 출력되고

let은 에러가 나버린다.

 

JS는 위에서 아래로 순차적으로 실행하기에

없는걸 출력하라고 한 시점에서 에러가 떠야하는게 맞다.

그렇다면 var는 왜 undefined가 출력되는가.

var name;
console.log(name);
name = 'Tarel'

실제 코드가 동작한 순서가 이렇기 때문이다.

 

즉 var라는 변수는 일단 그 자체만으로 최상단으로 이동한다 (값은 남겨진체로!)

그렇기 때문에 name은 없는 것이 아닌, 값이 할당되지 않은 변수가 되어버린다.

 

이것은 엄청난 문제를 일으키며 이것이 바로 var가 문제아인 이유다

 

사실 호이스팅 자체는 let이나 const도 적용된다.

그러나 자바스크립트 내부의 TDZ라는 영역이 이를 막아주기 때문에

const나 let은 호이스팅이 일어나지 않는다고만 생각해주는 것이 편하다.

 

 

 

 

 

 

 

1. 클래스란?

쉽게말해 붕어빵 틀이다.

그리고 그 붕어빵 틀로 만들어 낸 붕어빵이 바로 인스턴스이다.

 

이렇게 말하면 오히려 더 헷갈릴수도 있으니

프로그래머답게 설명하자면

특정 기능을 하는 구문을 만들어 놓은 것이 클래스이고

그걸로 만들어 낸 새로운 것들이 인스턴스이다.

 

아래 예시를 보자

class User { 
}

const Tarel = new User();
Tarel.name = "Tarel";
Tarel.age = 'adult';
Tarel.tech = "Node.js";

console.log(Tarel.name); // Tarel
console.log(Tarel.age); // adult
console.log(Tarel.tech); // Node.js

class 라는 선언자를 통해 User를 만들었다

그리고 Tarel 이라는 객체를 새로 생성했는데

여기에 이름과 나이, 기술을 각각 넣었다.

 

 

2. this와 프로퍼티

전에 배웠던 this를 여기선 어떻게 쓸까?

class User {
  constructor(name, age, tech) { // User 클래스의 생성자
    this.name = name;
    this.age = age;
    this.tech = tech;
  }
}

const user = new User("Tarel", "adult", "Node.js"); // user 인스턴스 생성
console.log(user.name); // Tarel
console.log(user.age); // adult
console.log(user.tech); // Node.js

constructor는 클래스의 생성자다.

이걸 통해 class는 파라미터를 받을 수 있게 된다.

 

 

JS에서 사용하는 모든 값은 프로퍼티 값이고 이 프로퍼티가 함수면 메소드라고 배운바 있다.

즉, 함수가 객체에 들어가 있으면 메소드가 되는 것인데, 클레스에서도 이렇게 메서드를 만들 수 있다.

 

class User {
  constructor(name, age, tech) { // User 클래스의 생성자
    this.name = name;
    this.age = age;
    this.tech = tech;
  }

  getName() { return this.name; } // getName 메서드
  getAge() { return this.age; }  // getAge 메서드
  getTech() { return this.tech; } // getTech 메서드
}

const user = new User("Tarel", "adult", "Node.js"); // user 인스턴스 생성
console.log(user.getName()); // Tarel
console.log(user.getAge()); // adult
console.log(user.getTech()); // Node.js

 

하나하나 살펴보자.

User라는 클래스에는 파라미터 역할을 해줄 constructor 가 선언이 되어 있고

이름과 나이, 기술을 받는다.

 

그리고 그 아래 3개의 함수가 있으니 이는 각각 입력받은 것을 출력하는 것이다.

 

user라는 변수는 클레스 User를 받아와 constructor에 Tarel, adult, Node.js를 순서대로 넣었고

user라는 변수에 있는 함수 3개를 각각 출력한 것이다.

 

 

3. 상속이란?

 

클래스는 상속이 가능하다.

이로인해 부모클래스와 자식클래스로 나뉠 수 있는데

부모는 자식에게 자신의 메서드, 변수 등과 같은 것을 자식  클래스에게 줄 수 있다.

 

코드가 길어질 것 같으니 최대한 짧게 짧게 해보자

class User {                           // User 부모 클래스
    constructor(name, age) {           // 부모 클래스 생성자
      this.name = name;
      this.age = age;

    }
    getTech(){ return this.age; }        // 부모 클래스 getTech 메서드
    add(a,b){return a+b}
  }
  
  class Employee extends User{          // User로부터 물려받은 첫번째 자식
    constructor(name, age) {            // 자식 클래스 생성자
      super(name, age);
    }
  }
  class Alice extends User{             // User로부터 물려받은 두번째 자식
    constructor(name) {                 // 자식 클래스 생성자
      super(name);
    }
    power = "Fire!!"
    a = super.add(1,2)
  }



  
  const employee = new Employee("Tarel", "adult", "Node.js");
  const girl_1 = new Alice("Alice", "young", "TripleMath");

  console.log(employee.name);                              //Tarel
  console.log(employee.age);                               //adult
  console.log(employee.getTech());                         //adult
  console.log(girl_1.age);                                 //undefined   //없는걸 요구하면 이렇게 된다.
  console.log(girl_1.power);                               //Fire!!
  console.log(girl_1.a);					// 3

시작하기 전에 여기서 super란 무엇일까

자세히보면 super는 자식이 쓰고 있는것을 볼 수 있는데 super란 부모를 부르는 것과 같다.

두번째 자식인 Alice 클래스를 보면 한번은 super(name)이라고 적혀있고

그 아래에는 a = super.add(1,2)가 있다.

두 가지 경우중 첫번째는 부모클래스의 생성자(constructor)를 호출한 것이고

두번째는 부모클래스가 가지고 있는 함수중 하나를 참조한 것이다.

 

첫번째 자식을 보자

constructor를 통해 name과 age를 순서대로 파라미터로 받는다(이때, 선언문을 보면 3개의 값이 들어갔는데 이중 마지막 값은 버려진다.)

 

그렇게 받은 두 값은 부모를 참조하여 각각 name과 age에 넣는다.

getTech 메서드는 호출되면 나이를 리턴하고

add 메서드는 a와 b를 받으면 그걸 더한 값을 반환한다.

 

 

이런식으로, 클래스는 자주쓰는 명령들의 집합이고

constructor는 클래스가 파라미터를 받아야할 때 쓰는 것이며

그 외에도 여러가지 변수나 함수등을 넣어 하나의 세트로 만들고

 

그 세트메뉴를 여러 클래스가 공유하면서 저마다 다른 기능을 가지게 할 수 있는 것이다.

 

 

비유를 하자면 모든 직원에게 똑같이 똑같은 책상을 지급했고 그 위에는 같은 컴퓨터를 배치했지만

직원마다 책상 위에 있는 물품들은 종류에서 차이가 있을 수 있다.

이때 직원에게 공통으로 지급된 것이 부모클래스, 저마다 개성있는 물품을 배치한 것은 자식클래스라고 할 수 있다. 

 

 

 

시작하기 전에

 

전에 포스팅 했던 내용과 겹치는 부분이 많다.

객체 편을 다 읽었다면 이 부분은 그냥 가볍게 읽고 넘어가도 된다.


1. 객체에 대한 복습

      객체는 단 하나의 값만 나타내는 원시타입

      다양한 값을 하나로 묶은 복잡한 형태인 객체타입으로 나뉜다.

 

자바스크립트는 객체기반의 언어고 객체로 대부분 구성되기에 이를 이해하는 것이 대단히 중요하다.

 

2. 객체 리터럴이란?

리터럴: 사람이 이해할 수 있는 형태로 값을 생성하는 표기법

즉, 객체 리터럴이란 객체를 생성하기 위한 표기법이다.

 

그냥 쉽게말해 객체를 만든다고 생각하면된다.

그렇다면 이전에 배운 객체 생성방식과 달라진 점은 무엇인가??

그냥 이게 더 쉽고 간결하기 때문에 다들 이거 쓴다.

정도로 이해하면 된다.

 

자, 만들어보자

참고로 객체로 만들어 진것은 자료형이 object로 나와야 한다.

let a = {}
console.log(a)
console.log(typeof(a))

// 결과
// {}
// object

참쉽죠?

 

는 너무 짧으니까 이번엔 뭐라도 넣어보자

 

let a = {
  Key: 'Value'
}

console.log(a)
console.log(typeof(a))
console.log(a.Key)
console.log(typeof(a.Key))

// 결과
// {Key: "Value"}
// object
// Value
// string

아까 선언한 a에다가 Key를 넣어주었고 그 Key의 값은 Value라고 정의했다

a를 출력하면 a의 전체가 나오고

a의 자료형 종류를 출력하면 객체라고 나오며

a라는 객체가 가진 Key의 값을 출력하자 Value가 나오는 것을 알 수 있다.

그리고 그 Value의 형태는 문자열이다.

 

여기서 Key : 'Value'에 해당하는 것이 바로 프로퍼티이다.

즉 a는 하나의 프로퍼티를 가진 객체이다.

프로퍼티는 키와 값으로 나뉜다.

눈치 챘겠지만 Key가 키고 value가 값이다.

뭔가 말장난처럼 보이겠지만 아무튼 :를 기준으로 왼쪽이 키, 오른쪽이 값이다.

 

 

자, 하나를 더 넣어보자

let a = {
  Key: 'Value',					//작성할때 주의할 것이, 여러개 넣을 땐 쉼표를 넣어야한다.
  abc: function(){
    return "Fxxk you World";
  }
}


console.log(a.abc())

//결과
//Fxxk you World

삶이 고단하다보면 욕이 나올 수도 있는 법이다.

사실 hello world를 넣으려다가 뭔가 진부해서 살짝 변형을 해봤다

 

아무튼 이번엔 a라는 객체에 abc라는 키를 넣었고 abc의 값으로는 function(){return "Fxxk you World"}가 입력되었다.

fuction은 알다시피 함수이다.

 

즉 abc에 함수가 들어간 형태다.

이러한 형태를 메서드라고 한다.

 

앞서 a.Key 를 console.log에 찍었을 때는 value라는 값이 찍혔다.

그렇다면 a.abc()를 console.log에 찍으면 어떻게 되느냐?

그 함수가 실행되는 것을 알 수 있다.

 

 

a
Key 'Value'
abc   abc: function(){
    return "Fxxk you World";
  }

이쯤되면 객체란 일종의 표나 다름없다는 것을 눈치 챘을 것이다.

a는 이 표의 이름이고

2개의 열에 다수의 행이 들어갈 수 있는 표 말이다.

 

 

약간 변형을 해보자

let a = {
  name: 'Tarel',
  'his age': 'adult'
}

이번엔 출력을 따로 하지 않았다.

뭐가 특이한지 눈치챘는가?

 

바로 his age가 따옴표가 들어있다는 점이다.

띄어쓰기는 key의 값으로 사용할 수 없다.

즉 his age : adult 는 성립되지 않는다.

그러나 따옴표 안에 가둠으로써 Key 값으로 넣을 수 없는 것(띄어쓰기 말고도 꽤 있다.)들을 Key 값으로 만들 수 있다.

물론 딱히 추천하지는 않는다.

그냥 이런게 있다고 생각하고 넘어가자

 

 

 

정리

객체 리터럴은 그저 객체를 간결하고 보기좋게 선언하는 방법이다.

프로퍼티는 객체 안에 있는 요소로써 키와 값으로 구성된다.

메서드는 프로퍼티의 값이 함수인 경우를 말한다.

 

 

 

이번은 사실상 객체에 대한 복습이자 객체를 다른 방식으로 표현하는 법에 대해 알아보는 것과 같았다.

 

그런고로 지난 포스팅을 읽었다면 적당히 가볍게 보고 넘어가도 될 것이다.

 

 

시작하기 전에......

 

이 글은 JavaScript 공부정리 - 객체 - 기본편 에서 이어진다.

 

1. JSON 객체

2. Math 객체

3. 외부 Script 파일 읽기

3-1. Lodash 라이브러리


1. JSON 객체

JSON이란 JavaScript Object Notation의 약자로 자바스크립트의 객체처럼 자료를 표현하는 방식이다.

 

다음은 JSON을 사용한 예시다.

 

이번에도 어김없이 등장하는 게임캐릭터, 오른쪽은 지난 포스팅에서 보았던 오리라는 캐릭터고

왼쪽은 쿠라는 캐릭터로 NPC다.

이름 오리
성별 알 수 없음 암컷
종족 알 수 없음 부엉이
능력 1 삼단점프() 비행()
능력 2 돌진() 없음

 

이 둘의 특징을 정리하면 이렇게 될 것이다.(사실 지난 포스팅에서 능력을 4개씩이나 적은건 너무 많아보여서 줄였다.)

 

이걸 JSON을 사용해서 표현해보자

[{
	"name": "Ori",
	"sex": undefined,
	"race": undefined,
 	"ability_1": "tripleJump()",
	"ability_2": "bash()"
}, {
	"name": "Ku",
	"sex": "female",
	"race": "owl",
 	"ability_1": "flight()",
	"ability_2": undefined
}]

JSON에는 몇가지 규칙이 있다.

1. 값은 문자열, 숫자, 불 만 사용할 수 있으며 함수 등은 사용이 불가능 하다.

2. 문자열은 반드시 큰 따옴표만 써야한다.

3. 키에도 반드시 따옴표를 붙여야한다.

 

자바스크립트 객체를 JSON 문자열로 변환할 때는 다음을 사용한다.

JSON.stringify()

예를 들어, 위의 캐릭터 변환한다고 한다면

 

const data = [{
	"name": "Ori",
	"sex": undefined,
	"race": undefined,
 	"ability_1": "tripleJump()",
	"ability_2": "bash()"
}, {
	"name": "Ku",
	"sex": "female",
	"race": "owl",
 	"ability_1": "flight()",
	"ability_2": undefined
}]

console.log(JSON.stringify(data))
console.log(JSON.stringify(data, null, 2))

이런식으로 작성한다.

이때 변환코드는 console에 작성했다.

파라미터를 보면 변수명 외에도 null과 2가 있는 것이 보이는데

2번째 파라미터는 어떤 속성만 선택해서 추출하고 싶을때 쓰며, null이기 때문에 전부 가져온다.

3번째 파라미터는 들여쓰기를 뜻한다.

때문에 위의 코드를 재생하면 다음과 같은 결과가 나온다.

[{"name":"Ori","ability_1":"tripleJump()","ability_2":"bash()"},{"name":"Ku","sex":"female","race":"owl","ability_1":"flight()"}]
[
  {
    "name": "Ori",
    "ability_1": "tripleJump()",
    "ability_2": "bash()"
  },
  {
    "name": "Ku",
    "sex": "female",
    "race": "owl",
    "ability_1": "flight()"
  }
]

첫줄은 첫번째 console.log 명령어가 출력한 것이고

두번째줄부터는 두번째 console.log 명령어가 출력한 것이다.

 

보통 첫번째 console.log 결과물 처럼 쓰고 2번째 경우는 잘 쓰지 않는다.

 

JSON 문자열을 자바스크립트 객체로 전개할 때는 다음을 사용한다.

JSON.parse()

 

예를 들어, 위 캐릭터에 사용한다면

const data = [{
	"name": "Ori",
	"sex": undefined,
	"race": undefined,
 	"ability_1": "tripleJump()",
	"ability_2": "bash()"
}, {
	"name": "Ku",
	"sex": "female",
	"race": "owl",
 	"ability_1": "flight()",
	"ability_2": undefined
}]

const json = JSON.stringify(data)	//자료를 JSON으로 변환
console.log(JSON)

console.log(JSON.parse(json))		//JSON문자열을 다시 자바스크립트 객체로 변환

 

이를 출력하면 다음과 같다.

 

[{"name":"Ori","ability_1":"tripleJump()","ability_2":"bash()"},{"name":"Ku","sex":"female","race":"owl","ability_1":"flight()"}]

Array(2)
0:{name: "Ori", ability_1: "tripleJump...}	//이하생략
1:{name: "Ku", sex: "female", race: "o...}	//이하생략

2. Math 객체

이름에서 볼 수 있듯, 수학과 관련된 기본적인 연산을 할 때 사용한다.

pi, e와 같은 수학상수를 속성으로 가지며 sin(), cos(), tan()같은 삼각함수도 있다.

참고로 pi는 원주율로 3.1415926535....를 가지며

e는 자연로그로 2.718281828......를 가진다.

 

수학을 다루는 만큼 속성이 다양한데 하나하나 다 알기엔 너무 많지만

적어두면 쓸 곳이 많아보이므로 이곳에 정리한다.

 

참고로 삼각함수는 파라미터와 반환값 모두 호도법을 사용한다.

라디안 값을 각도로 바꾸르면 Math.PI / 180 을 하면 되고

반대로 각도 값에 곱하면 라디안 값이 된다.

 

이름 설명 값(있는 경우)
Math.E 자연로그의 밑 약 2.718......
Math.LN2 2의 자연로그 약 0.693......
Math.LN10 10의 자연로그 약 2.303......
Math.LOG2E 밑이 2인 로그 E 약 1.443......
Math.PI 원주율 약 3.141592......
Math.SQRT1_2 0.5의 제곱근 약 0.707......
Math.SQRT2 2의 제곱근 약 1.414......
Math.abs(x) x의 절댓값 반환  
Math.sin(x) x의 사인 값 반환  
Math.cos(x) x의 코사인 값 반환  
Math.tan(x) x의 탄젠트 값 반환  
Math.asin(x) x의 아크사인 값 반환  
Math.acos(x) x의 아크코사인 값 반환  
Math.atan(x) x의 아크탄젠트 값 반환  
Math.asinh(x) x의 쌍곡아크사인 값 반환  
Math.acosh(x) x의 쌍곡아크코사인 값 반환  
Math.atanh(x) x의 쌍곡아크탄젠트 값 반환  
Math.atan2(y, x) 인수 몫의 아크탄젠트 값 반환  
Math.cbrt(x) x의 세제곱근 반환  
Math.floor(x) 인수보다 작거나 같은 수 중 가장 큰 정수를 반환  
Math.ceil(x) 인수보다 크거나 같은 수 중 가장 작은 정수를 반환  
Math.clz32(x) 주어진 32비트 정수의 선행 0개수 반환  
Math.exp(x) E^x를 반환, 여기서 E는 자연로그의 밑  
Math.expm1(x) 위의 exp(x)에서 1을 뺀 값을 반환  
Math.fround(x) 인수의 가장 가까운 단일 정밀도 표현을 반환  
Math.hypot([x[,y[,......]]]) 인수의 제곱합의 제곱근을 반환  
Math.imul(x,y) 두 32비트 정수의 곱을 반환  
Math.log(x) x의 자연로그(e를 밑으로 하는) 값, 즉 ln 값을 반환  
Math.log1p(x) x+1의 자연로그 값을 반환  
Math.log10(x) x의 로그값(여기서 밑은 10)을 반환  
Math.log2(x) x의 로그값(여기서 밑은 2)를 반환  
Math.max([x[,y[,......]]]) 0개 이상의 인수에서 제일 큰 수를 반환  
Math.min([x[,y[,......]]]) 0개 이상의 인수에서 제일 작은 수를 반환  
Math.pow(x,y) x의 y제곱을 반환  
Math.random() 0과 1 사이의 난수를 반환  
Math.round(x) x와 가장 가까운 정수를 반환  
Math.sign(x) x가 양이면 1을, 음이면 -1을 반환  
Math.sqrt(x) x의 제곱근을 반환  
Math.toSource() 문자열 Math를 반환 쓰지 말 것
Math.trunc(x) x의 정수부분만 반환(즉, 소수를 버림)  

3. 외부 Script 파일 읽기

 

프로그래밍 규모가 커지면 파일 하나가 너무 방대해지기 때문에 파일을 분리하는 것이 좋다.

고로 파일을 분리 하는 방법과 분리된 파일을 쓰는법에 대해 알아보자

 

여기서는 HTML을 사용해야 한다.

별도의 스크립트 파일을 따로 만들어 주고 HTML에서 불러와 보자

참고로 <head>안에서의 내용만을 다루고 <body>는 생략한다.

또한 쓸모 없다고 여겨지는 부분 또한 생략했다.

<head>
	<script src="test.js"></script>
</head>

자신과 같은 경로에 있는 test.js 파일을 불러오게 하는 명령이다.

 

 

3-1. Lodash 라이브러리

내가 만든 자바스크립트 파일 뿐만 아니라 타인이 만든 자바스크립트 파일을 쓸 수도 있다.

이를 외부라이브러리 라고 한다.

유틸리티 라이브러리는 개발시 보조적으로 사용하는 함수들을 제공해주는 라이브러리이다.

여러종류가 있지만 최근에 많이 쓰는 것이 바로 Lodash 라이브러리 이다.

lodash.com에서 해당 라이브러리를 다운받을 수 있다.

 

 

 

+ Recent posts