dh_0e

[JavaScript] 주요 문법 정리(3) ( 문서 객체 모델(DOM), Class와 상속, 클로저(Closure) ) 본문

내일배움캠프/HTML,CSS,JavaScript

[JavaScript] 주요 문법 정리(3) ( 문서 객체 모델(DOM), Class와 상속, 클로저(Closure) )

dh_0e 2024. 4. 26. 02:45

DOM이란

Document(HTML파일)를 Javascript가 해석할 수 있는 Object 형태로 Moudeling 한 것
브라우저에 기본적으로 내장되어 있는 API 중 하나

( API는 다른 시스템에서 제공하는 기능을 사용할 수 있도록 도와주는 중간자 역할 )

DOM Tree


DOM이 브라우저에 내장되어있기 때문에 우리는 HTML의 내용을 Javascript로 접근, 제어할 수 있다.
DOM은 node를 갖는다. (계층구조, DOM Tree 내부의 하나 하나 모두 node)

 

DOM에 접근하는 방법

document.getElementById("ID") ID의 코드를 불러옴
document.querySelector(".Class") Class의 태그를 불러옴 (ID도 #으로 불러올 수 있음)
.children 자식 요소 불러옴
.parent 부모 요소 불러옴

 


클래스(Class)

 

constructor - 생성자

클래스 안에 getters, setters를 함수 형태로 만들어 생성자 포함 class의 속성을 바꾸거나 불러올 때 호출됨
무한 호출이 될 수 있으므로 underscore this._변수명 을 사용하여 java의 private처럼 사용해야함

class Person {
    constructor(name, age) {
        this._name = name;
        this._age = age;
    }

    get name() {
        return this._name;
    }
    set name(value) {
        if (typeof value !== "string") {
            console.log("name type must be string");
            return;
        }
        this._name = value;
    }

    get age() {
        return this._age;
    }
    set age(value) {
        if (value <= 0) {
            console.log("age must be bigger than zero");
            return;
        }
        this._age = value;
    }
    sayHello() {
        console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
    }
}

const person = new Person('kdh', 23);
console.log(person); // Person { name: 'kdh', age: 23 }

// getter 예시
console.log(person.name); // kdh
// setter 예시
person.name=123; // name type must be string
person.age = -1; // age must be bigger than zero
// 함수 호출 예시
person.sayHello(); // Hello, my name is kdh and I'm 23 years old.


상속(Inheritance)

Class를 유산으로 내려주는 주요 기능
class 자식 extends 부모 {} - 부모에게 내려받은 메서드를 재정의할 수 있음 - 함수 오버라이딩(overriding)
super(바뀐 내용을 부모에게 알려주기)

class Animal {
  constructor(name, age, sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;
  }
  scream() {
    console.log(`${this.name} makes a noise.`);
  }
}

class Man extends Animal {
  constructor(name, age) {
    super(name, age, "male");
  }

  scream() {
    console.log(`${this.name} : 으아악!`);
  }
}

let Fubao = new Animal('Fubao', 5, 'Female');
Fubao.scream(); // Fubao makes a noise.

let kdh = new Man('kdh');
kdh.scream(); // "kdh : 으아악!"

console.log(Fubao); // Animal { name: 'Fubao', age: 5, sex: 'Female' }
console.log(kdh); // Man { name: 'kdh', age: undefined, sex: 'male' }


static 메소드

정적 메소드로 Class를 인스턴스하지 않아도 바로 메소드처럼 사용할 수 있음

class Calculator {
  static add(a, b) {
    return a + b;
  }

  static subtract(a, b) {
    return a - b;
  }
}

console.log(Calculator.add(1, 2)); // 3
console.log(Calculator.subtract(3, 2)); // 1

 

 

 

클로저(Closure)

클로저는 함수와 그 함수가 선언된 렉시컬 환경(=outer)과의 조합

 

[렉시컬 스코프]

JS 엔진은 함수를 어디서 호출했는지가 아니라 어디에 정의했는지에 따라서 스코프(상위 스코프)를 결정
즉 외부 렉시컬 환경에 대한 참조값(=outer)은 함수 정의가 평가되는 시점에 결정된다는 의미

 

외부 함수보다 중첩 함수가 더 오래 유지되는 경우, 중첩 함수는 이미 생명 주기가 종료한 외부 함수의 변수를 여전히 참조 >> 즉, 중첩 함수가 종료했는데 여전히 끝난 함수의 변수를 참조 >> closure
이는 가비지 컬렉터가 안 쓰는 것만 가져가며,

중첩 함수가 필요로 하는 '생명 주기가 종료한 외부 함수의 데이터'를 남겨놓았기 때문

const x = 1;

function outer() {
  const x = 10;
  const inner = function () {
    console.log(x);
  };
  return inner;
}

const innerFunc = outer();
innerFunc(); // 10

위 코드에서 outer()의 생명 주기가 종료했지만 중첩 함수 inner에서 x의 값을 참조하고 있기 때문에 죽지 않고 값을 남김

 

 

클로저의 활용

클로저는 상태를 안전하게 변경하고 유지하기 위해 사용 (상태를 안전하게 은닉한다)

const increase = (function () {
  let num = 0; // 클로저로 죽지 않고 은닉되어 increase로만 수정 가능

  return function () {
    return ++num;
  };
})(); // 함수를 실행한 값을 increase에 대입한다는 의미

console.log(increase()); // 1
console.log(increase()); // 2
console.log(increase()); // 3