[내배캠] 5/2 14일차

초이·2024년 5월 2일
0

🗓️ 내일배움캠프

목록 보기
14/55
post-thumbnail

DOM

DOM이란?

그전에 javascript의 탄생 이유를 알아야 한다.

  • 브라우저에서 쓰려고 만들어진 것.
  • 웹 페이지를 동적으로 만들기 위해! html문서를 조작하면 움직(기능)이게 하고 싶어서 만들어진 것이다.

페이지 동작 과정

  1. 사용자가 브라우저에 주소를 입력한다. (즉, 클라이언트가 서버에 요청(request)한 것.)
  2. HTML 문서를 서버로부터 수신한다.
    1. 서버는 클라이언트에게 응답(response)한다.
  3. 브라우저가 HTML 파일을 해석(parsing)한다.
    1. 브라우저엔 렌더링 엔진(크롬, 사파리 등)이 있다.

    2. 렌더링 엔진이 html 문서를 렌더링(해석)한다.

      해석이 왜 필요할까?
      이유는 javascript가 서버로부터 받은 파일을 알아들을 수 없기 때문이다. 따라서 이해하기 쉽게 해석하는 과정이 필요하다.

    3. 렌더링 엔진이 HTML을 알아보기 좋게 DOM Tree, CSS를 CSSOM Tree로 만든다음 묶어서 Render Tree를 구성한다.

      Render Tree ?
      HTML, CSS 및 JavaScript 문서를 파싱(해석)해서 브라우저에 실제로 렌더링되는 최종 문서 모델을 나타내는 객체의 계층 구조이다.

DOM

Document(HTML)를 javascript가 이해하게 Object 형태로 Modeling 한 것.

  • 브라우저에 기본적으로 내장되어있는 API 중 하나.

    API란?
    다른 시스템에 데이터나 서비스를 요청할 때, API는 해당 시스템과 사용자 간의 인터페이스 역할을 한다.
    따라서, API는 다른 시스템에서 제공하는 기능을 사용할 수 있도록 도와주는 중간자 역할을 한다.

    따라서, 브라우저에게 DOM 객체를 접근할 수 있게 도와주는 것이기 때문에 API가 되는 것. 또한, DOM관련 여러 API가 존재한다.
  • DOM으로 우리는 HTML의 내용을 javascript로 다음과 같은 기능을 수행할 수 있다.
    • 접근
    • 제어
  • 모든 DOM의 node속성메서드를 가지고 있다.

    Node란?
    HTML태그, text, 속성 등이 합쳐진 것을 블록으로 만든 것을 node라고 한다.

    DOM node의 속성과 메소드
    쉽게 얘기하자면 값이 속성, 동작을 수행하는게 메서드

    document.getElementById('div').innerHTML = 'hi';
    • getElementById('div') : 메서드
    • innerHTML: 속성

Class

ES6에서 처음 도입된 개념

javascript는 객체지향언어다. 다른 언어에서 클래스 기반으로 프로그래밍을 한 개발자들에 의해 js에서도 class 개념이 도입되었다.

클래스와 인스턴스

클래스(class)

객체를 생성하기 위한 변수나 속성, 메서드의 템플릿.

class Person {
	construtor(name, age){
		this.name = name;
		this.age = age;
	}
	sayHello() {
		console.log(`hi I'm ${this.name}`);
	}
}

//인스턴스 생성
const person1 = new Person("james");
person1.sayHello(); //hi I'm james
  • construtor
    • class의 생성자 함수이다. 객체를 생성할 때 호출되고 객체를 초기화시키는 역할을 한다.
    • constructor는 매개변수를 받아서 this.name과 this.age로 속성을 초기화 한다.

Getter/Setter

값을 가지고 set할 때 검증을 할 수 있다.

class Rectangle {
  constructor(height, width) {
    this._height = height; //private하게 사용하기위해 _를 쓴다
    this._width = width;
  }

  get width() {
    return this._width;
  }

  set width(value) {
	  //검증, 유효성 검사
    if (value <= 0) {
      console.log("error");
    } else if (typeof value !== "number") {
      console.log("enter the number");
      return;
    }
    this._width = value;
  }

  get height() {
    return this._height;
  }

  set height(value) {
	  //검증, 유효성 검
    if (value <= 0) { 
      console.log("error");
    } else if (typeof value !== "number") {
      console.log("enter the number");
      return;
    }
    this._height = value;
  }

  getArea() {
    const a = this._width * this._height;
    console.log(`넓이는 ${a}입니다.`);
  }
}

//rec1의 너비와 높이 지정해줌
const rec1 = new Rectangle(10, 20);
//rec1의 넓이를 구하는 함수를 호출
rec1.getArea();

언더바를 쓰지않으면 콜스택이 꽉차서 불러오는데 문제가 있다.

상속(Inheritance)

//부모 클래스
class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(`${this.name} say hi`);
  }
}

//상속
class Dog extends Animal {
  //부모에게 있는 메서드를 재정의 할 수 있음
  //overRiding.
  speak() {
    console.log(`${this.name} barks!`);
  }
}

const pupps = new Dog("long");
pupps.speak();
  • Dog 클래스가 Animal 클래스를 상속 받는다.
  • 그런데 부모 클래스에 있는 메소드(speak)를 재정의하였는데 이것을 오버라이딩(overRiding)이라고 한다.

정적 메소드 (static method)

  • 인스턴스(instance)를 호출할 수 없고 class이름으로 직접 호출할 수 있는 메소드를 의미한다.
  • 이 메소드는 인스턴스를 만들지 않아도 사용할 수 있기 때문에 유틸리티 함수, 정적 속성인 경우 인스턴스 간 복제가 필요없는 데이터(똑같은것을 공유)를 만들때 사용된다. → 인스턴스 만들 필요 없을 때 쓴다.
class Calculate {
  static add(a, b) {
    console.log("더하기: ");
    return a + b;
  }

  static substr(a, b) {
    console.log("빼기: ");
    return a - b;
  }
}

//이렇게 바로 class에서 메소드를 호출한다.
console.log(Calculate.add(3,5)); //8

클로저

클로저란?

클로저는 함수와 그 함수가 선언된 렉시컬 환경과의 조합이다.

const x = 1;

function outer() { //전역에 선언
  const x = 10;
  function inner() { //outer 안에서 선언
    console.log(x); // 10이 나온다.
  }
  inner(); 
}

outer();

====================================

const x = 1;

function outer(){ //전역에 선언
	const x = 10;
	inner();
}

function inner(){ //전역에 선언
	console.log(x); //1
}

outer();

위 코드를 봤을 때, JS는 함수를 호출한 scope(지역)보다 “선언”한 scope에 따라서 상위 스코프를 결정한다.

클로저와 렉시컬 환경(lexical Environment)

외부 함수보다 중첩 함수가 더 오래 유지 되는 경우(어디 호출된게 아직 안 끝남), 중첩 함수는 이미 생명 주기가 종료한 외부 함수의 변수를 여전히 참조할 수 있다.

아래 예시를 보자

const x = 1;

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

const innerFunc = outer();
innerFunc();

[순서]

  1. outer가 선언 되어있고, innerFunc에 outer를 담았다.
  2. outer는 선언과 동시에 사라지고 innerFunc가 호출되었다.
  3. innerFunc안에는 outer 함수가 넣어져있으니까 outer함수 안의 코드가 실행된다.
  4. 실행하니까 inner가 선언되었고 inner를 반환한다.
  5. inner에는 x를 출력하는 코드가 있다.
  6. 이 inner의 scope는 outer안에 있기 때문에
  7. 이미 종료된 outer의 변수인 x를 여전히 참조하게 되는 것이다.

→ 이게 클로저다.

[가능한 이유]

  • 가비지 콜렉터가 똑똑하게도 참조되는 변수가 있는 함수면 종료가 되어도 삭제하지 않는 것

클로저의 활용

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

const increase = (function () {
	//카운트 상태 변수
	let num = 0;
	//클로
	return function() { //이 함수가 즉시실행되면서 increase에 할당
		return ++num;
	};
})();

console.log(increase()); //increase의 즉시실행함수는 사라졌지만
//상위 스코프를 기억하는 반환된 함수가 있다.
//num이 +1되고 그 변수를 소멸된 즉시실행 함수에 저장
//그러면 private한 변수가 되어서 increase를 사용할 때만 변경할 수 있는것.

[순서]

  1. 즉시 실행 함수가 호출되면서 즉시 실행 함수가 반환한 함수가 increase가 변수에 할당된다.
  2. increase 변수에 할당된 함수는 자신이 정의된 위치에 의해 결정된 상위 스코프인 즉시 실행 함수의 렉시컬 환경을 기억하는 클로저다.
  3. 즉시 실행 함수는 호출과 동시에 소멸되지만, 즉시 실행 함수가 반환한 클로저는 increase 변수에 할당되어서 호출된다.
  4. 이때, 클로저가 자신이 정의된 위치에 의해 상위 스코프인 즉시 실행 함수의 렉시컬 환경을 기억하고 있다.
  5. 따라서 즉시 실행 함수가 반환한 클로저는 카운트 상태를 유지하기 위한 자유 변수 num을 언제 어디서 호출하고 참조, 변경할 수 있다.
  6. num은 초기화 되지 않으며, 외부에서 직접 접근할 수 없이 은닉된 private 변수이므로 전역 변수를 사용하는 방식과 달리 변경될 걱정을 할 필요가 없다..
profile
개발 일기장

0개의 댓글