들어가기 전

C++, JAVA 같은 클래스 기반 객체지향 프로그래밍 언어의 특징인 클래스와 상속, 캡슐화를 위한 키워드인 public, private, protected 등이 없어서 JavaScript는 객체지향 언어가 아니라고 오해하는 경우도 있다. 하지만 JavaScript는 클래스 기반 객체지향 프로그래밍 언어보다 효율적이며 더 강력한 객체지향 프로그래밍 능력을 지니고 있는 프로토타입 기반의 객체지향 프로그래밍 언어다.

자바스크립트는 객체 기반의 프로그래밍 언어이며 자바스크립트를 이루고 있는 거의 '모든 것'이 객체다. (원시타입 제외)

 

객체지향 프로그래밍

프로그래밍에서 필요한 데이터를 추상화시켜 속성과 메서드를 가진 객체를 만들고

객체 간의 상호작용을 통해 로직을 구성하는 프로그래밍 패러다임

 

객체지향 프로그래밍 4가지 특징

1. 추상화

2. 상속

3. 캡슐화

4. 다형성

 

1. 추상화

- 객체들이 공통적으로 필요로 하는 속성이나 행위를 추출

- 불필요한 정보는 숨기고 중요한 정보만을 표현함으로써 프로그램을 간단하게 만드는 것

2. 상속

- 클래스의 속성과 행위를 하위 클래스에게 물려주거나 하위 클래스가 상위 클래스의 속성과 행위를 물려 받는 것

- 새로운 클래스가 기존의 클래스의 데이터와 연산을 이용할 수 있게 하는 기능

3. 캡슐화

- 데이터 구조와 데이터를 다루는 방법들을 결합시켜 묶는 것 (변수와 함수를 하나로 묶는 것)

- 낮은 결합도를 유지할 수 있도록 설계하는 것

4. 다형성

- 하나의 변수명, 함수명이 상황에 따라 다른 의미로 해석 될 수 있는 것

- 요소에 여러 개념을 넣어 놓는 것

하나의 클래스 내부에 같은 이름의 행위를 여러개 정의하거나 상위 클래스의 행위를 하위 클래스에서 재정의하여 사용할 수 있기 때문에 다형성을 갖게 될 수 있다.

 

오버라이딩 : 상위 클래스가 가지고 있는 메서드를 하위 클래스가 재정의해서 사용
오버로딩 : 같은 이름의 메서드가 인자의 개수나 자료형에 따라 다른 기능을 하는 것

 

 

객체 지향 프로그래밍의 장단점

장점 단점
클래스 단위로 수정이 가능하기 때문에 유지 보수가 편리 객체의 수가 많아짐에 따라 용량이 커질 수 있음
클래스를 재사용하거나 상속을 통해 확장함으로써 코드 재사용이 용이 처리 속도가 상대적으로 느림 (절차지향과 비교)
클래스 단위로 모듈화시켜서 개발하기 때문에 업무 분담이 편리하고 대규모 소프트웨어 개발에 적합 설계시 많은 시간과 노력이 필요하게 될 수 있음

 

SOLID (객체 지향 설계 원칙)

1. 단일 책임 원칙 (SRP, Single Resposibility Principle)

- 하나의 클래스는 단 하나의 책임만 질 것

- 지키지 않으면 변경에 의해 다른 책임과 관련된 코드에 영향이 갈 수 있다

 

2. 개방-폐쇄 원칙 (OCP, Open/Closed Principle)

- 소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다

- 기능을 변경하거나 확장할 수 있으면서 기능을 사용하는 코드는 수정하지 않는다

 

3. 리스코프 치환 원칙 (LSP, Liskov Substitution Principle)

- 프로그램 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 함

- 상위 타입의 객체를 하위 타입의 객체로 치환해도, 상위 타입을 사용하는 프로그램은 정상적으로 동작해야한다.

 

4. 인터페이스 분리 원칙 (ISP, Interface Segregation Principle)

- 범용 인터페이스 하나보다 클라이언트를 위한 여러 개의 인터페이스로 구성하는 것이 좋다

- 인터페이스는 인터페이스를 사용하는 클라이언트를 기준으로 분리해야 한다

- 클라이언트가 필요로 하는 인터페이스로 분리함으로써 각 클라이언트가 사용하지 않는 인터페이스에 변경이 있어도 영향을 받지 않도록 만들어야 한다

 

5. 의존관계 역전 원칙 (DIP, Dependency Inversion Principle)

- 추상화에 의존

- 고수준 모듈은 저수준 모듈의 구현에 의존해서는 안되고 저수준 모듈은 고수준 모듈에서 정의한 추상 타입에 의존해야한다.

 

객체지향 OOP에 대해서 간단히 포스팅했는데 부족한 부분에 대한 보충 설명은 추후에 하겠습니다.

 

https://jongminfire.dev/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%B4%EB%9E%80

https://www.yes24.com/Product/Goods/9274256

 

 

모던 자바스크립트 Deep Dive - 예스24

『모던 자바스크립트 Deep Dive』에서는 자바스크립트를 둘러싼 기본 개념을 정확하고 구체적으로 설명하고, 자바스크립트 코드의 동작 원리를 집요하게 파헤친다. 따라서 여러분이 작성한 코드

www.yes24.com

 

'Javascript' 카테고리의 다른 글

[JS] Class 작동원리  (0) 2024.11.15
[JS] 클로저와 스코프  (0) 2024.10.17
[JS] reduce() 에 대해서  (0) 2024.06.20
[JS] 동기(synchronous) 비동기(asynchronous)  (0) 2024.05.13
[JS] 구조 분해 할당  (0) 2024.04.24

출처 : https://www.yes24.com/Product/Goods/92742567

 

모던 자바스크립트 Deep Dive - 예스24

『모던 자바스크립트 Deep Dive』에서는 자바스크립트를 둘러싼 기본 개념을 정확하고 구체적으로 설명하고, 자바스크립트 코드의 동작 원리를 집요하게 파헤친다. 따라서 여러분이 작성한 코드

www.yes24.com

 

Class 란 무엇인가?

- 프로토타입객체를 생성하기 위한 템플릿

- ES6 생긴 문법 (ES6 이전에도 생성자 함수로 프로토타입 객체를 생성할 수 있었음)

- 새로운 객체를 생성하는 메커니즘

- 읽는 사람 or 작성하는 사람이 편하게 디자인 된 문법(문법적 설탕)으로 직관적인 특징을 지님

객체지향
프로그램을 객체들로 구성하고 서로 상호작용을 통해 구현하는 방법 (방법론)

프로토타입
코드를 그들의 클래스들에 의존시키지 않고 기존 객체들을 복사할 수 있도록 하는 생성 디자인 패턴
프로토타입을 통해 객체지향 언어의 상속을 구현

프로토타입 기반 언어
모든 객체들이 메소드와 속성들을 상속 받기 위한 템플릿으로써 프로토타입 객체를 가진다

 

Class의 특징

- new 연산자가 있어야 호출이 가능

- 상속을 지원하는 extends와 super 키워드를 제공 (상속 관계 구현을 간결하고 명료하게함)

- 생성자 함수 기반의 객체 생성방식보다 견고하고 명료

 

Class는 어떤 타입일까?

// 클래스 선언문
class Person {}

console.log(typeof Person); // function

클래스 선언문으로 정의한 클래스는 함수 선언문과 같이 소스코드 평과 과정, 즉 런타임 이전에 먼저 평가되어 함수 객체를 생성한다. 이 때 클래스가 평가되어 생성된 함수 객체는 생성자 함수로서 호출할 수 있는, 즉 constructor다. 생성자 함수로서 호출할 수 있는 함수는 함수 정의가 평가되어 함수 객체를 생성하는 시점에 프로토타입도 더불어 생성된다. 프로토타입과 생성자 함수는 단독으로 존재할 수 없고 언제나 쌍으로 존재하기 때문이다.

 

Class 클래스는 클래스 정의 이전에 참조가 불가능

console.log(Person);
// 참조 에러 ReferenceError : Cannot access 'Person' before initiailization

// 클래스 선언문
class Person {}

 

Class의 메서드의 종류

- Class 에 정의할 수 있는 메서드 3개

1. constructor (생성자)

2. 프로토타입 메서드

3. 정적 메서드

 

1. constructor (생성자)

> constructor는 인스턴스를 생성하고 초기화 하기 위한 특수한 메소드

class Person {
  // 생성자
  constructor(name){
    // 인스턴스 생성 및 초기화
    this.name = name;
  }
}

// class는 인스턴스를 생성하기 위한 생성자 함수
console.log(typeof Person); // function
console.dir(Person);

// 모든 함수 객체가 가지고 있는 prototype 프로퍼티가 가리키는 프로토타입 객체의
// constructor 프로퍼티는 클래스 자기 자신을 가리킴.
// 클래스가 인스턴스를 생성하는 생성자 함수를 의미

 

2. 프로토타입 메서드

> 생성자 함수를 사용하여 인스턴스를 생성하는 경우 프로토타입 메서드를 생성하기 위해서는 다음과 같이 명시적으로 프토타입 메서드를 추가해야한다.

class Person {
  // 생성자
  consturctor(name) {
  	// 인스턴스 생성 및 초기화
    this.name = name;
  }
  
  // 프로토타입 메서드
  sayHello(){
  	console.log(`Hello! My name is ${this.name}`);
  }
}

const me = new Person('Jaka');
me.sayHello(); // Hello! My name is Jaka

 

3. 정적 메서드

> 정적 메서드는 인스턴스를 생성하지 않아도 호출할 수 있는 메서드를 의미.

class Person {
  // 생성자
  constructor(name){
    this.name = name;
  }
  
  // 정적 메서드 : class에서는 앞에 static을 붙여야함
  static sayHello() {
    console.log('Hello');
  }
}

Person.sayHello(); // Hello
// 인스턴스를 생성하면 TypeError가 뜬다.

 

 

클래스 인스턴스 생성과정

1. 인스턴스 생성과 this 바인딩

- new 연산자와 함께 클래스를 호출하면 constructor의 내부 코드가 실행되기 전 암묵적으로 빈객체가 생성

 (빈 객체는 미완성된 클래스가 생성한 인스턴스)

- 이때 클래스가 생성한 인스턴스의 프로토타입으로 클래스의 프로토타입 프로퍼티가 가리키는 객체가 설정

- 그리고 암묵적으로 생성된 비 객체, 즉 인스턴스는 this에 바인딩 됨

- 따라서 constructor 내부의 this는 클래스가 생성한 인스턴스를 가리킴

 

2. 인스턴스 초기화

- constructor의 내부 코드가 실행되어 this에 바인딩 되어 있는 인스턴스를 초기화.

(this 바인딩 되어 있는 인스턴스를 추가하고 constructor가 인수로 전달받은 초기값으로 인스턴스의 프로퍼티값을 초기화.)

 

3. 인스턴스의 반환

- 클래스의 모든 처리가 끝나며 완성된 인스턴스가 바인딩된 

class Person {
  // 생성자
  constructor(name) {
  	// 1. 암묵적으로 인스턴스가 생성되고 this에 바인딩
    console.log(this); // Person {}
    
    // 2. this에 바인딩되어 있는 인스턴스를 초기화
    this.name = name;
    
  	// 3. 완성된 인스턴스가 바인딩된 this가 암묵적으로 반환
  }
}

'Javascript' 카테고리의 다른 글

[JS] 객체 지향 프로그래밍 (OOP)  (0) 2024.11.28
[JS] 클로저와 스코프  (0) 2024.10.17
[JS] reduce() 에 대해서  (0) 2024.06.20
[JS] 동기(synchronous) 비동기(asynchronous)  (0) 2024.05.13
[JS] 구조 분해 할당  (0) 2024.04.24

 

목차

1.  클로저란?

2.  어휘적(Lexical) 환경

3.  스코프 (블록 스코프 / 함수 스코프 / 렉시컬 스코프)

 

 

 

클로저 - JavaScript | MDN

클로저는 주변 상태(어휘적 환경)에 대한 참조와 함께 묶인(포함된) 함수의 조합입니다. 즉, 클로저는 내부 함수에서 외부 함수의 범위에 대한 접근을 제공합니다. JavaScript에서 클로저는 함수 생

developer.mozilla.org

출처 : https://developer.mozilla.org/ko/docs/Web/JavaScript/Closures

 

1. 클로저

클로저는 주변 상태(어휘적 환경)에 대한 참조와 함께 묶인(포함된) 함수의 조합이다. 

즉, 클로저는 내부 함수에서 외부 함수의 범위에 대한 접근을 제공한다.

Javascript에서 클로저는 함수 생성 시 함수가 생성될 때마다 생성한다.

 

(쉽게 말하면 함수 안에 함수가 정의 될 때 감싸고 있는 함수에 접근할 수 있는 것을 의미한다.)

 

2. 어휘적(Lexical)  환경

function start(){
  var name = "Jaka";
  function viewName(){
    // viewName() 은 내부 함수이며, 클로저.
    console.log(name); // 부모 함수에서 선언된 변수를 사용
  }
  viewName();
}

start();

 

start() 는 지역 변수 name과 함수 viewName() 을 생성한다. viewName() 은 start() 안에 정의된 내부 함수이며 start() 함수 본문에서만 사용가능하다. viewName() 내부엔 자신만의 지역변수가 없다는 점이다. 내부함수는 외부함수의 변수에 접근할 수 있기 때문에 start()를 실행하면 viewName() 가 실행되어 "Jaka"가 출력되는 것을 확인할 수 있다.

 

- let / const 를 사용한 범위 지정

var 사용

JavaScript에는 함수 스코프와 전역 스코프 두 가지만 존재했다. var로 선언한 변수는 함수 내부 또는 외부에서 선언 되었는지에 따라 함수 스코프나 전역 스코프를 가지게 된다.

if (Math.random() > 0.5) {
  var x = 1;
} else {
  var x = 2;
}

console.log(x); // 1 or 2 가 출력되며 에러가 발생하지 않는다.

 

위에 코드에서는 에러가 발생하지 않은데 그 이유는 var로 선언한 변수에 대해 스코프를 생성하지 않기 때문이며, 여기서 var 는 전역변수를 생성한다. 

 

let / const 사용

ES6에서, JavaScript는 블록 스코프 변수를 생성할 수 있도록 let과 const 로 변수를 선언했을 때만 유효한다.

if (Math.random() > 0.5){
  let x = 1;
} else {
  let x = 2;
}

console.log(x); // 에러 발생

 

ES6부터는 블록은 스코프로 취급되기 시작했다지만, let과 const 로 변수선언 했을 때만 유효하다.

 

클로저(Closure)

function testFunc() {
  const name = "Jaka";
  function displayName() {
    console.log(name);
  }
  return displayName;
}

const myTest = testFunc();
myTest();

// Jaka 가 출력됨

 

이 함수는 displayName() 내부 함수가 실행되기 전에 외부 함수에서 반환된다. 이 코드가 정상적으로 동작할 수 있는 이유는 JavaScript의 함수가 클로저를 형성하기 때문이다 . 클로저는 앞서 말했듯이 함수와 함수가 선언된 어휘적 환경의 조합이다. 이 환경은 클로저가 생성된 시점의 유효범위 내에 있는 모든 지역 변수로 구성된다.

 

위의 코드 경우에는, myTest는 testFunc이 실행 될 때 생성된 displayName 함수의 인스턴스에 대한 참조다. displayName의 인스턴스 변수 name이 어휘적 환경에 대한 참조를 유지한다. 이런 이유로 myTest가 호출될 때 변수 name은 사용할 수 있는 상태로 남게 되고 "Jaka"가 console.log에 전달된다.

 

3.  스코프 (함수 스코프 / 블록 스코프 / 렉시컬 스코프)

- 스코프는 쉽게 말해서 변수에 접근할 수 있는 범위이다.

- 변수 또는 표현식이 "해당 스코프" 내에 있지 않다면, 사용할 수 없다.

- 스코프는 계층적인 구조를 기지기 때문에, 하위 스코프는 상위 스코프에 접근할 수 있지만 반대는 불가능하다.

 

함수 스코프

특정 함수 내에 어떠한 블록이 있다면, 해당 블록 내에 있는 변수는 해당 함수 내에서도 접근할 수 없고 오직 그 블록 내에서만 접근이 가능하다.

function f1() {
  var x = 0;
  {
    var x = 1;
    console.log(x);  // 1
  }
  console.log(x);  // 1
}

f1(); // var는 블록내에서만 유효하지 않아서 x가 1이 두번 찍히는 것을 확인할 수 있다.

 

블록 스코프

let과 const 로 변수를 선언하면 블록 스코프를 가진다. let 과 const 는 변수 선언된 블록 내에서만 유효하다.

function f1(){
  let x = 0;
  {
    let x = 1;
    console.log(x); // 1
  }
  console.log(x); // 0
}

f1();

 

렉시컬 스코프

함수의 위치에 따라 함수의 상위 스코프가 정해지는데 이 상위 스코프가 정해지는 시점이 함수의 선언인지 함수의 실행인지에 따라 함수의 상위 스코프가 달라진다.

 

함수의 상위 스코프가 함수가 실행되는 시점에서의 상위 스코프로 정해지는 것을 정적 스코프 또는 렉시컬 스코프라고 한다.

'Javascript' 카테고리의 다른 글

[JS] 객체 지향 프로그래밍 (OOP)  (0) 2024.11.28
[JS] Class 작동원리  (0) 2024.11.15
[JS] reduce() 에 대해서  (0) 2024.06.20
[JS] 동기(synchronous) 비동기(asynchronous)  (0) 2024.05.13
[JS] 구조 분해 할당  (0) 2024.04.24

reduce란?

reduce() 메서드는 배열의 요소를 하나로 줄이는 작업을 수행하는 함수다.

reduce 함수로 배열의 각 요소를 순회하면서 누적된 값을 계산하고 최종 결과를 반환할 수 있다.

reduce 형태

array.reduce(callback[, initialValue]);

array : reduce를 적용할 배열
callback : 배열의 각 요소에 대해 실행할 콜백 함수. 콜백함수는 다음과 같은 매개변수를 가진다
- accumulator : 콜백 함수의 반환 값 또는 이전 순회에서의 최종 결과값. 초기값이 제공된 경우 첫번째 순회에서는 initialValue로 설정 된다.
- currentValue : 현재 순회 중인 배열의 요소
- currentIndex (옵션) : 현재 순회 중인 배열의 요소 인덱스
- array ( 옵션) : reduce 함수가 호출된 배열

 

initialValue (옵션) : 콜백 함수의 첫번째 순회에서 accumulator로 사용될 초기 값 초기 값이 제공되지 않으면 배열의 첫번째 요소가 초기값이 된다.

 

반환 값

배열을 순서대로 불러 각 요소에 대해 콜백함수 실행한 결과를 누적한 값

 

1. 배열값 모두 더하기

const num = [1, 2, 3, 4, 5]

const sum = num.reduce((accumulator, currentValue) => accumulator + currentValue, 0);

console.log(sum); // 출력값 : 15​



2. 객체가 들어간 배열에서 원하는 값만 더하기

const student = [
  {
    name : "jaka1",
    age : 30
  },
  {
    name : "jaka2",
    age : 40
  },
  {
    name : "jaka3",
    age : 50
  }
]

const sumAge = student.reduce((acculmulator, currentValue) => acculmulator + currentValue.age,0);

console.log(sumAge); // 출력값 : 120

 

3. 중첩 배열 배열로 만들기

const numArray = [
  [0, 1],
  [2, 3],
  [4, 5]
]

console.log(numArray.reduce((accumulator, currentValue) => accumulator.concat(currentValue), []);

// 출력값 : [0, 1, 2, 3, 4, 5]

 

'Javascript' 카테고리의 다른 글

[JS] Class 작동원리  (0) 2024.11.15
[JS] 클로저와 스코프  (0) 2024.10.17
[JS] 동기(synchronous) 비동기(asynchronous)  (0) 2024.05.13
[JS] 구조 분해 할당  (0) 2024.04.24
[JS] 쿠키 세션 로컬스토리지  (0) 2024.04.23

목차

1. 동기와 비동기

2. 자바스크립트의 비동기 처리

3. promise 객체

4. async 와 await

 

1. 동기와 비동기

동기

- 직렬적으로 작업을 수행한다.

- 요청을 보낸 후 응답을 받야지만 다음 동작을 실행한다. 작업을 처리하는 동안 나머지 작업은 대기한다.

 

비동기

- 병렬적으로 작업을 수행하는 방식이다.

- 요청을 보낸 후 응답의 수락 여부와는 상관 없이 다음 업무가 동작하는 방식이다.

- 비동기 처리를 위해 콜백 패턴을 사용하면 콜백함수가 중첩되어 복잡도가 높아질 단점이 있다. 이를 콜백지옥이라고 부른다. (가독성이 나빠질 수 있다.)

 

2. 자바스크립트의 비동기 처리

Web API

Web API는 브라우저에서 제공되는 API. 자바스크립트 엔진에서 정의되지 않았던 setTimeout이나

HTTP 요청(ajax) 메소드, DOM 이벤트 등의 메소드를 지원한다.

 

Task Queue

이벤트 발생 후 호출되어야 할 콜백 함수들이 대기하는 공간. 이벤트 정한 순서대로 줄을 서있고 콜백 함수들이 기다리는 공간이라고 해서 콜백큐(Callback Queue) 라고 부른다.

 

Event Loop

함수의 실행 순서를 정해준다.

setTimeout(()=>{
  console.log("안녕");
},3000) // 3초 뒤에 실행할 함수

function a(){
  console.log("안녕1");
  console.log("안녕2");
  console.log("안녕3");
}

// 함수 실행은 안녕1, 안녕2, 안녕3, 안녕 순서대로 한다.

 

1. Call Stack 안녕(setTimeout)이 먼저 쌓이고 Web API에  3초 동안 콜백함수가 가지게 된다.

2. Call Stack에 안녕1이 쌓이고 출력, 안녕2가 쌓이고 출력, 안녕3이 쌓이고 출력된다.

3. Call Stack이 다 호출되면 안녕(setTimeout)이 3초후에 Task Queue에 호출되고 Event Loop가 정해준 순서로 실행된다. 

 

주의 : Call Stack이 다 호출되면 SetTimeout이 호출되기 때문에 Call Stack에 호출이 된 양이 많으면 setTimeout에서 정해준 시간이 정확하지 않을 수 있다.

 

3. Promise 객체

비동기 처리를 할 때 사용

대기, 이행, 거부의 반환값과 메서드를 가지고 있는 객체

const promise = new Promise((resolve, reject) => {
  if("성공"){
    resolve("성공했어");
  }
  if("실패"){
    reject("실패했어");
  }
});
//Promise 객체 생성
// 인자로 생성자 함수에 콜백함수를 전달한다.
// resolve 성공의 결과를 반환해줄 함수 (첫번째 매개변수)
// reject 실패의 결과를 반환해줄 함수 (두번째 매개변수)

Promise 상태

Pending(대기) : 이행하지도 거부하지도 않은 대기 상태

Fullfilled(이행) : 데이터 처리를 성공함 (pending -> fullfilled)

Rejected(거부) : 데이터 처리를 실패함 (pending -> rejected)

 

then / catch

const promise = new Promise((resolve, reject) => {
  if("성공"){
    resolve("성공했어");
  }
  if("실패"){
    reject("실패했어");
  }
});
//Promise 객체 생성
// 인자로 생성자 함수에 콜백함수를 전달한다.
// resolve 성공의 결과를 반환해줄 함수 (첫번째 매개변수)
// reject 실패의 결과를 반환해줄 함수 (두번째 매개변수)

/////////////// then catch //////////////////
promise.then((result)=> {console.log(result});
// 비동기 처리를 한 뒤에 성공 결과를 반환

promise.catch((error) => {console.log(error});
// 비동기 처리를 한 뒤에 실패 결과를 반환

const callbackPromise = (text, time) => {
  return new Promise((resolve, reject) => {
    try{
      // 코드 정상 실행
      setTimeout(()=>{
        resolve(text);
      }, time);
    } catch(e){
      // 코드 정상 실행 X
      reject(e);
    }
  })
}

callbackPromise("text 0", 1000)
.then((result) => {
  console.log(result);
  return callbackPromise("text 1", 1000);
})
.then((result) => {
  console.log(result);
  return callbackPromise("text 2", 1000);
})
.then((result) => {
  console.log(result);
  return callbackPromise("text 3", 1000);
})
.catch((result) => {
  console.log(result);
});

// text 0 ~ text 2까지 1초 간격으로 출력됨

 

then은 성공한 결과값을 호출하는 메서드로 매개변수로 반환받은 함수를 받는다. 

 

4. async 와 await

const asyncFn = async () ={
  try{
    // promise 객체의 대기 상태
    const text1 = await callbackPromise("text", 1000);
    // await 뒤에 promise 대기상태이면 코드를 밑으로 진행시키지 않는다.
    // pomise 객체의 대기 이후에 처리 결과를 반환
    console.log(text);
    
    const text2 = await callbackPromise("text2", 1000);
    console.log(text2);
    
    const text3 = await callbackPromise("text3", 1000);
    console.log(text3);
    
    return test1;
  }
  catch(e){
    console.log(e);
  }
}
console.log(asyncFn());
// text1 ~ text3 1초에 하나씩 출력됨

 

 

'Javascript' 카테고리의 다른 글

[JS] 클로저와 스코프  (0) 2024.10.17
[JS] reduce() 에 대해서  (0) 2024.06.20
[JS] 구조 분해 할당  (0) 2024.04.24
[JS] 쿠키 세션 로컬스토리지  (0) 2024.04.23
[JS] DOM 구조 / javascript로 html 접근  (1) 2024.04.18

목차

1. 구조 분해 할당

2. 배열 분해

3. 객체 분해

4. 나머지 패턴

 

1. 구조 분해 할당

배열이나 객체의 속성을 해체하여 그 값을 개별 변수에 담을 수 있게 하는 JavaScript 표현식

객체나 배열에 저장된 데이터 전체가 아닌 일부만 필요한 경우를 위해서 객체나 배열을 변수로

분해할 수 있게 해주는 특별한 문법

 

 

2. 배열 분해

// 배열 만들기
  let arr = ["사과", "바나나", "포도"]

  // 구조분해 할당을 이용해
  // apple엔 arr[0]
  // banana arr[1]
  // grape arr[2]을 할당
  let [apple, banana, grape] = arr;
  
  console.log(apple); // 사과
  console.log(banana); // 바나나
  console.log(grape); // 포도

 

3. 객체 분해

 let myInfo = {
    name : "Jaka",
    age : 30,
    tel : 12345678
  };

  let {name, age, tel} = myInfo;
  console.log(name); // Jaka
  console.log(age); // 30
  console.log(tel); // 12345678

 

4. 나머지 

프로퍼티 개수가 할당하려는 변수의 개수보다 많을 때

나머지를 할당할 때 사용합니다.

  let desk = {
    material: "tree",
    color: "red",
    weight : 80
  };

  // rest = 나머지 프로퍼티
  let{material, ...rest} = desk
  console.log(rest.color); // red
  console.log(rest.weight); // 80

목차

1. 쿠키

2. 세션 스토리지

3. 로컬 스토리지

 

1. 쿠키

- 쿠키는 유효기간이 있으며 서버로 전송되는 작은 텍스트 파일

- 서버로부터 정송된 쿠키는 웹 브라우저에 저장되며, 이후 해당 웹 사이트를 방문할 때마다

  해당 쿠키는 서버로 전송됩니다.

-  쿠키는 일반적으로 사용자 식별, 장바구니, 선호설정, 장바구니 등의 정보를 저장하는데 사용됩니다.

유효기간이 지나면 삭제됩니다.

function createCookie(name, value, time){
  // 썩은 쿠키는 유효하지 않는다.
  // 시간을 넣지 않고 쿠키를 생성하면 세션 쿠키 지속 계속 되는 쿠키
  let date = new Date();
  // ms로 시간을 증가된 값을 만들어서 
  // 1000 = 1초

  // 1일 이후의 시간을 만들면
  // time === 일 단위
  // time === 2면 2임
  date.setTime(date.getTime() + time * 24 * 60 * 60 * 1000); // ms setTime : 수정하겠다.
  document.cookie = name + "=" + value + ";" + "expires=" + date.toUTCString() + ";" + "path=/" 
  //page=/ domain까지 로그인했을
}

console.log(new Date().getTime());

createCookie("devOps2", 86858585, 1);
createCookie("devOps3", 1242143, 1);
console.log(document.cookie);
// [[devOps2,123], [devOps3, 1242143]]

// 문자열을 잘라서 가져오는 함수를 만들자
function getCookie(name){
  let arr = document.cookie.trim().split(";");
  let result = undefined;
  for (let i = 0; i < arr.length; i++){
    arr[i] = arr[i].trim().split("=");
    console.log(arr[i][0]);
    if (arr[i][0].trim() === name){
      result = arr[i][1];
    }
  }
  console.log(arr);
  console.log(result)
  return result;
}
getCookie("devOps3")

 

2. 세션 스토리지

- 서버에 불필요한 데이터를 저장하지 않습니다.

- 브라우저를 종료할 때까지 인증상태를 유지(탭/윈도우가 닫히면 세션 스토리지는 초기화)

- 쿠키보다 보안이 뛰어납니다.

// 세션에 값을 저장
// setTime
sessionStorage.setItem("토큰", "데이터의 내용");

// 세션의 값을 호출
// 토큰의 키가 있으면 데이터를 호출
sessionStorage.getItem("토큰");

// 모든 세션을 전체 삭제
sessionStorage.clear();

// 세션 하나 제거
sessionStorage.removeItem("토큰");

 

3. 로컬 스토리지

- 브라우저 창을 닫더라도 데이터가 유지됩니다.

- 서버에 불필요한 데이터를 저장하지 않습니다.

- 자동로그인에 사용됩니다.

// 로컬 스토리지는 큰 데이터를 저장할 때 사용한다.
localStorage.setItem("토큰", "데이터의 내용");

localStorage.getItem("토큰");

localStorage.clear();

localStorage.key(0);

// 객체를 문자열로 변환하면 obeject
// JSON 문자열로 변경

let obj = { name : "자카" };
console.log(String(obj)); // Object Object 출력
// String 생성자 : 전달받은 인자를 문자열로 변환

// 컴퓨터와 컴퓨터는 데이터를 주고받을 때 문자열로 주고 받는다
console.log(JSON.stringify(obj)); // 문자열로 변환
// 데이터를 보낼 준비
obj = JSON.stringify(obj); // 다시 배열로 변환
// 데이터를 전달받은 서버

let arr = [{name : "자카"}, {name : "자카박"}];
localStorage.setItem("todo",JSON.stringify(arr));

let obj2 = localStorage.getItem("todo");
console.log(obj2);
obj2 = JSON.parse(obj2);
console.log(obj2);

 

 

 

DOM (Document Object Model)

브라우저가 웹 문서를 이해할 수 있도록 구성된 것
html 태그를 동적으로 제어한다
브라우저가 html 페이지를 로드하는 과정에서 태그들은 각기 하나의 객체로 만든다.
html 문서의 내용을 노드트리 구조의 객체들로 나타낸다.

 

요소 선택
자바스크립트에서 DOM 요소를 조작하기 위해서 사용

document ( html 문서의 내용이 들어있다.)

document.getElementById("header")  // header 라는 아이디를 가지고 있는 요소를 찾아서 반환
document.createElement("span");  // span 태그 데이터를 생성 (HTML에는 나오지 않는다.)
!! HTML에 내용을 추가하기위해서 append를 사용한다. !!

header.innerHTML = ""; // 태그 요소 안에 내용을 넣을 수 있다.
header.innerTEXT = ""; // 태그 요소 안에 텍스트 내용을 넣을 수 있다.

 

DOM 구조를 이용한 게시판 만들기

function createContent(index, title, content){
    let _li = document.createElement("li");
    let _span01 = documnet.createElement("span");
    let _span02 = documnet.createElement("span");
    let _span03 = documnet.createElement("span");
    
    // li span span span --> 생성만 함 (변수로만 가지고 있다.)
    // 필요한건 내용 추가하고 span을 li에 넣어줘야한다.
    
    _span01.innerHTML = index;
    _span02.innerHTML = title;
    _span03.innerHTML = content;
    _li.append(_span01);
    _li.append(_span02);
    _li.append(_span03);
    
    // 배열로 설명
    document.querySelector(".border").append(_li);
}

// 데이터베이스의 내용을 받아서
// DTO (Data transfer Object)
// 데이터를 우리가 사용할 형태로 변경해서 받아온다.

let arr = [{index : 1, title : "제목1", content : "내용"}]

function render(){
    document.querySelector(".border").innerHTML = `
        <li>
          <span>인덱스</span>
          <span>제목</span>
          <span>내용</span>
        </li>
    `;
    for(let i = 0; i < arr.length; i++){
        createContent(arr[i].index, arr[i].title, arr[i].content);
    }
}

function postContent(){
    let _title = title_input.value;
    // 아이디 활용 value input 에 입력한 값
    let _content = content_input.value;
    const content = {
        index : arr.length + 1;
        title : _title,
        content : _content
    }
    arr.push(content); // 배열에 요소 추가 (push)
    render();
}

 

 

 

 

목차

1. 객체

2. 클래스

 2 - 1 클래스 상속 (extends, super)

 

 

1. 객체

 

객체는 참조형 데이터 타입

하나의 사물을 표현하는 여러 데이터를 다룰 때 사용

 

데이터 타입

원시형 : string, number, boolean 등

참조형 : object, array, function

// 객체 문법
// 리터럴 문법
const user = {};
console.log(user);

// 생성자 문법
// new 예약어
const user = new Object();
console.log(user);

const computer = {
    name : "gram",
    model : 15,
    color : "white",
    sell : false,
    price : 165000
};

// 객체는 실제 존재하는 개체를 표현할 때 작업
// 객체에는 여러 키와 값이 존재하고 특정값을 호출할 수 있어야한다.

// 객체의 name만 호출 해보기
// 점 표기법
console.log(computer.name) === "gram";

// 괄호 표기법
console.log(computer["name"]) === "gram";

// 점 표기법과 괄호 표기법 차이
// 속성 특수문자 접근, 매개변수를 속성으로 접근할 때
// 괄호 표기법을 사용한다
const content = {
    "content-type" : "text/javascript"
};
content["content-type"];

function objProperty(obj, key){
    console.log(obj["name"]);
}
objProperty(computer, "name");

const student = {
    age : 30,
    phone : "01012345432",
    city : "서울"
};

const student2 = {
    age : 30,
    phone : "01012345432",
    city : "서울",
    say : function(){
        console.log(this) // this는 객체 안에 있다.
    }
};

student2.say();

function createStudent(age, phone, city){
    this.age = age;
    this.phone = phone;
    this.city = city;
}

const student3 = new createStudent(22, "01066661111", "부산");
console.log(student3); // 배열 출력
console.log(student3.age); // 22
console.log(student3.city); // 부산

// new 생성자 문법을 사용하면 윈도우 객체가 아닌 빈객체에 값이 생긴다

 

 

2. 클래스

 

클래스는 객체를 만들기 위해 사용되는 방법중 하나 클래스를 사용하면 코드의 가독성이 좋아지고

상속을 통한 코드의 재사용성이 좋아집니다. (만약 클래스가 없었다면 객체를 하나 생성할 때마다

코드가 길어져서 불편해졌을겁니다.)

class Student {
    // class 생성시 첫문자 대문자
    // 생성자 함수
    // constructor : 최초에 한번 new로 객체를 생성할 때
    constructor(_age, _phone, _city){
        this.age = _age;
        this.phone = _phone;
        this.city - _city;
    }
    // get 호출 조회 할 때 사용할 메서드
    get getAge(){
        return this.age;
    }
    
    // set 수정을 할 때 사용할 메서드
    set setAge(_age){
        this.age = _age
    }
    
    // static 정적 메서드 클래스로 객체를 만들 때 생성되지 않는다.
    // 클래스 안에 있는 자원을 가지고 기능을 작성해야할 경우
    static myfn(age, phone, city){
        let obj = new student(age, phone, city);
        obj.age = this.age;
    }
}

let obj = new Student(20, "01012341234", "서울");
console.log(obj); // 배열 생성

obj.getAge(); // 클래스에 있는 함수 호출시 객체에 담아서 사용한다.

Student.myfn(); // static은 클래스 안에 있는 자원을 가지고 있어서 함수 호출시
                // 클래스 명을 가져온다

 

부모 클래스 자식 클래스

class Mother {
    constructor(_name, _age){
        this.name = _name;
        this.age = _age;
    }
    getInfo() {
        return `이름 : ${this.name} / 나이 : ${this.age}`;
    }
}

class Child extends Mother {
    // extends 부모클래스에서 자식클래스에게 상속할 때 사용
    constructor(_hp, mp, _atk, _name, _age){
		super(_name, _age); // super 부모 클래스의 생성자 함수를 호출
        this.hp = _hp;
        this.mp = _mp;
        this.atk = _atk;
    }
	getState(){
    	return `hp : ${this.hp} / mp : ${this.mp} / atk : ${this.atk}`;	
    }
    
    setHp(_hp){
    	this.hp = _hp;
    }
    
    static getAtk(n) {
        return n.atk
    }
}

let character1 = new Child(100, 80, 200, "자카", 31);
let character2 = new Child(150, 70, 180, "자카팍", 33);

console.log(character1.getInfo()); // 이름 : 자카 / 나이 : 31
console.log(Child.getAtk(character2)); // 180

 

 

자바스크립트를 이용해서 클래스를 이용한 팝업창 만들기

class Popup {
    constructor (_popupWrap){
        this.popupWrap = _popupWrap;
    }
    
    setPopupOpen(){
    	// classList 요소에 가지고 있는 모든 클래스의 리스트
        // contains 클래스를 가지고 있는지 확인 === true false
        if (this.popupWrap.classList.contains(".popup-wrap")){
            // true 클래스를 가지고 있으면 팝업이 켜짐
            this.popupWrap.classList.remove("is-active");
        } else {
            // false 클래스를 추가
            this.popupWrap.classList.add("is-active");
        }
    }
}

let popup = new Popup(document.querySelector(".popup-wrap"));

목차

1. 재귀 함수

2. 스택과 큐

3. 자바스크립트 메모리 

   3 - 1 원시타입

   3 - 2 참조 타입

4. 배열

 

1. 재귀 함수

재귀함수는 함수의 내용에서 다시 자신을 호출해서 반복 작업을 하는 방식입니다. for 문으로도 반복문을 구현 가능한 로직들은 재귀 함수로 작성이 가능합니다. 재귀 함수를 사용하는 이유는 반복하는 내용의 기능을 여러개로 나누고 직관적으로 관리할 때 사용하는 프로그래밍 패턴 중 하나입니다.

재귀 함수를 작성할 때는 더이상 나눠야 할 필요가 없을 때 종료됩니다.
문제를 나눠서 기능을 작성하는 경우는 이 두가지 패턴을 찾아서 활용해야합니다.

 

 

재귀함수로 반복문을 사용한 예

function sum(n, result){
    if (n === 5){
    	console.log(result);
    }
    sum(n + 1, result + n);
}
sum(1, 0);

// 출력값 : 10

 

재귀함수의 목적

장점으로 반복문을 많이 사용하는 경우보다 코드가 간결하고 직관적이다.

단점으로 스택에 함수 실행이 쌓여서 메모리 공간을 많이 차지하고 속도 성능이 저하된다.

 

재귀함수를 통한 피보나치 수열

function fibo(n){
    if(n == 1 || n == 2) return;
    return fibo(n - 1) + fibo(n - 2);
}

 

 

재귀 함수를 이용한 짝수 더하기

// 재귀함수로 짝수를 더하는 재귀적으로 돌리자
// 더하는 횟수는 인자값으로 전달 받아서
function sum(num, count){
    if(count <= 0) return;
    console.log(num);
    sum(num + 2, count - 1);
}
sum(2, 5);

// 출력 : 2 4 6 8 10

 

 

2. 스택과 큐

스택

스택은 LIFO (Last In First Out) 후입선출 방식으로 데이터를 저장하는 자료구조입니다. 이는 마지막으로 삽입된 데이터가 먼저 삭제되는 구조를 의미합니다. 스택은 삽입(push)과 삭제(pop)의 두가지 기본 연산으로 구성되며 삽입은 스택의 가장 위쪽에 데이터를 추가하는 것이고, 삭제는 스택의 가장 위쪽 데이터를 제거하는 것이다. 재귀함수를 호출 할때 사용합니다.

 

큐는 FIFO (First In First Out) 선입선출 방식으로 데이터를 저장하는 자료구조입니다. 이는 먼저 삽입된 데이터가 먼저 삭제되는 구조를 의미합니다. 큐 역시 스택과 마찬가지로 삽입(enmqueue)과 삭제(dequeue)의 두가지 기본 연산으로 구성됩니다. 큐는 탐색, 작업처리 대기열등에 사용되며, 컴퓨터 시스템의 프로세스 스케줄링에도 활용됩니다. 

 

3. 자바스크립트 메모리 

자바스크립트의 메모리 영역은 call stack과 heap이라는 영역이 있다.
call stack 메모리원시타입이 저장되고 heap 메모리에는 참조 타입이 저장됩니다. 

 

 

원시 타입

- string, number, boolean, undefined 등 메모리에 값을 저장하고 변수가 직접 값을 가르키는 것

- 원시타입은 재할당 하게되면 새로운 메모리에 재할당한 값을 저장하고 가르키는 주가 바뀌는 것

let a = 1;
a = 2;

// 이렇게 1과 2는 둘다 값이 존재하면서 새로운 메모리에 값을 재할당하고
// a가 가르키는 주소가 변한 것(이후 1은 사용되지 않으니 제거된다.)

 

참조 타입

- Array. Object, function 등 외에는 참조타입 입니다. 

- 원시타입과 다르게 참조타입은 변수의 크기가 동적으로 변합니다.

- 동적으로 데이터가 변하기 때문에 참조타입의 데이터는 heap메모리에 저장됩니다. 

- 변수를 호출해 주소의 값을 호출하면 힙 메모리에 주소의 값을 호출하고 힙메모리의 주소에 있는 값을 호출하게 됩니다.

let arr = [];
let arr2 = arr;

// push 메서드는 배열에 값을 뒤로 추가한다.
arr.push(1);
console.log(arr2);

 

원시타입은 값을 가르키는 주소를 가지고 있다.`

참조타입은 힙 메모리 주소를 가르키는 주소를 가지고 있다.

 

4. 배열

배열은 참조형 데이터 타입

// 문법
let arr = [];
let arr2 = ["javascript", 2, 3, 4, true];

// 0 인덱스 개념으로

// 배열의 값을 호출할 때
arr[0] === "javascript";

// 자바스크립트의 배열은 데이터의 타입이 동적 타입이다. (어떤 타입이라도 쓸 수 있음)
// length는 배열의 길이를 나타낸다.
// arr.length 배열의 길이를 확인하는 키와 값

// 이중 배열
let b = [[],[],[]];

// 배열의 값을 추가
// 배열의 맨 마지막 데이터 뒤로 값이 추가된다.
arr.push(1);

// 해당 인덱스에 값을 할당하는 경우
arr[0] = 1;
arr[1] = 2;

// 실습 배열을 하나 만들고 반복문을 10번 돌려서 배열에 증가하는 index

// 배열의 메서드
// index : 0, 1, 2, 3, 4, 5
let arr = [1, 2, 3, "javascript", 4, 5];

// indexOf 배열안에 값을 찾고 그 값이 들어있는 index를 반환
// 해당 값이 있는 인덱스를 찾아서 반환

arr.indexOf("javascript");

function indexOf(arr, str){
    // 배열의 길이만큼
    for(let i = 0; i < arr.length; i++){
    	// i가 0일 때는
        if(arr[i] == str)[{
        	return i;
            // 자바스크립트 인덱스가 몇번인지 알려줄 수 있다.
        }
    }
}

// find
// 배열의 값을 처음부터 순서대로 순화하며 true의 값을 찾으면
// 반복을 멈추고 해당 값을 반환
// 함수에서 값을 반환
let result = arr.find(function(i){
    return i === "javascript";
});

function find(arr, fn){
    for(let i = 0; i < arr.length; i++){
    	function(arr[i]){
        	return i === "javascript";
            // 1 false, 2 false, javascript true
        }
    }
    if(fn(arr[i])){
    	return arr[i];
    }
}

// findIndex
// 배열의 값을 처음부터 순서대로 순화하며 true 값을 찾으면
// 반복을 멈추고 해당 인덱스를 반환한다.
let result2 = arr.findIndex(function(i){
    return i === "javascript";
});

// filter
// 검색기능 구현할 때
// 새로운 배열을 만든다.

let arr2 = ['사과', '사과', '포도'];
// 배열을 반환한다.
// true 값을 받아도 배열의 끝까지 순회
// true값이 나온 해당 데이터를 배열의 형태로 만들어서 최종적으로 반환
// ['사과', '사과']
let result3 = arr2.filter(function(i){
    return i[0] === "사";
});
result3 = ['사과', '사과']; // 새로운 힙 메모리에 할당된 값

// map
// 배열의 값을 처음부터 순서대로 순회하면서
// 배열의 끝까지 반복한다. 배열을 반환한다. 반환된 값들을 가지고 배열을 생성.
let result4 = arr2.map(function(i){
    return "javascript";
});

// forEach : 배열의 문자열 변환
let a = [];
arr2.forEach(function(i){
    console.log(i);
    a.push(i);
});

// join : 배열을 만들어서 값을 깊은 복사
arr.join("*"); // 빈문자열이면 구분점에 내용 추가x

// 문자열을 배열로 변경
// split : 매개변수로 전달한 내용이 문자열에서 배열로 나눠질 구분점
 
arr.splice("*")
// "사과*사과*포도" 문자열 -> ["사과", "사과", "포도"] 배열 

// 배열을 깊은 복사 하는 경우
// 스프레드 연산자 용어
const arr = [1,2,3];
const arr2 = [...arr];

 

배열로 lotto 번호 6개 랜덤으로 뽑기

// 1. 로또는 겹치는 숫자가 나오면 안됨.
// 2. 숫자는 6개를 뽑아야 한다.
// 3. 나온 숫자들을 리스트 형태로 보여줘야함. (배열의 형태로 만들어줘야함)

// 로또 번호들이 들어갈 로또 박스
const lottoNum = [];

// 로또 구슬을 뽑아서 담아놓을 정답 배열
const result = [];

// 추첨 전에 세팅
// 초기화 단계
function lottoInit(){
    for(let i = 1; i <= 45; i++){
    	lottomNum.push(i);
        // lottoNum[i - 1] = i;
    }
    console.log("셋팅 끝남");
}

function play(){
    for(let i = 0; i < 6; i++){
         let randomIndex = parseInt(Math.random() * lottoNum.length);
         
         let number = lottoNum[randomIndex];
         // splice 원본 배열의 값을 제거하는데
         // 첫번째 인자가 시작 인덱스부터
         // 두번째 인자값은 갯수
         
         lottoNum.splice(randomIndex, 1);
         
         result.push(number);
    }
}

// 함수를 한꺼번에 호출하기
function main() {
    lottoInit();
    play();
    console.log("로또의 결과는?", result);
}

main();

 

'Javascript' 카테고리의 다른 글

[JS] DOM 구조 / javascript로 html 접근  (1) 2024.04.18
[JS] 객체(object), 클래스(class)  (0) 2024.04.17
[JS] 함수  (0) 2024.04.14
[JS] 반복문 (for / while)  (0) 2024.04.13
[JS] 스코프 / 조건문 (if문, switch문)  (0) 2024.04.12

+ Recent posts