반응형

 

 

 

 

extension

공식 문서 https://eslint.org/docs/latest/rules/

 

Rules - ESLint - Pluggable JavaScript Linter

A pluggable and configurable linter tool for identifying and reporting on patterns in JavaScript. Maintain your code quality with ease.

eslint.org

1. ESLint :

자바스크립트, 타입스크립트 코드의 규칙을 검사해주는 기능

.eslintrc.js 파일에서 규칙을 정의해준다.

 

2. .prettierrc

코드를 통일된 규칙으로 변경해주는 기능

ex) 따옴표를 싱글/더블 등으로 지정, 세미콜론 유무 등

 

반응형
반응형

제네릭 타입의 제약조건

원하지 않는 속성이 접근하는 것을 막기 위해 제네릭 타입에 제약조건을 걸어서 타입선언을 제한한다.

  • Constraints : 특정 타입들로만 동작하는 제네릭 함수를 만들 때 사용한다.
  • Keyof : 두객체를 비교할 때 사용한다.

 

Constraints 

const printMessage = <T extends string | number> (message: T) : T => {
	return message;
}

printMessage <string> ("1");
printMessage <number> (1);
printMessage <boolean> (true); // 에러 발생

keyof

const getProperty = <T extends object, U extends keyof T> (obj: T, key:U) => {
	return obj[key]
}

getProperty( {a:1, b:2, c:3}, "a" ); // return 1
getProperty( {a:1, b:2, c:3}, "z" ); // 에러

 

 

 

 

참고

https://typescript-kr.github.io/pages/generics.html

 

TypeScript 한글 문서

TypeScript 한글 번역 문서입니다

typescript-kr.github.io

 

 

 


팩토리 패턴 Factory pattern

팩토리 패턴

객체를 생성하는 인터페이스만 미리 정의하고, 인스턴스를 만들 클래스의 결정은 서브클래스가 내린다.

여러개의 서브클래스를 가진 슈퍼클래스가 있을 때, 입력에 따라 하나의 서브클래스 인스턴스를 반환한다.

 

일반적인 팩토리패턴

interface Car {
	drive(): void
    park(): void
}

class Bus implements Car {
	drive() : void { }
    park() : void { }
}

class Taxi implements Car {
	drive() : void { }
    park() : void { }
}

아래 CarFactory 클래스는, factory pattern을 적용하기 위한 서브 클래스이다.

제네릭 없이 팩토리패턴을 구현하면, 클래스가 새롭게 추가될 때마다 case도 추가되어져야 하는 불편함이 있다.

class CarFactory {
	static getInstance (type: String) : Car {
    	switch (type) {
        	case "bus": return new Bus();
        	case "taxi": return new Taxi();
        	// 클래스가 새롭게 추가되면 case도 추가되어져야 하는 불편함이 있다.
        }
    }
}

 

제네릭을 이용한 팩토리 패턴

interface Car {
    drive(): void
    park(): void
}

class Bus implements Car {
    drive() : void { }
    park() : void { }
}

class Taxi implements Car {
    drive() : void { }
    park() : void { }
}

class Suv implements Car {
    drive() : void { }
    park() : void { }
}

제네릭을 이용하면 새로운 클래스가 추가되어도,

Car를 implement한 모든 클래스를 대상으로 getInstance를 호출하기 때문에 추가적인 코드 수정이 필요없게 된다.

class CarFactory {
	static getInstance <T extends Car> (type: {new () : T}): T {
    	return new type();
    }
}

const bus = CarFactory.getInstance(Bus); 
const bus = CarFactory.getInstance(Taxi);
const bus = CarFactory.getInstance(Suv);

 

반응형
반응형

Generic 제네릭

 

제네릭

단일 타입이 아닌 다양한 타입에서 작동하는 컴포넌트를 작성할 수 있다.

사용자는 제네릭을 통해 여러 타입의 컴포넌트나 자신만의 타입을 사용할 수 있다.

 

코드를 작성할 때 타입을 미리 정하지않고 코드 실행시 타입을 지정하고 싶은 경우, 제네릭을 사용한다.

(코드 작성시 식별자 T, U, V를 이용: <T> <U> <V>)

 

 

제네릭을 사용하는 이유

재사용성이 높은 함수와 클래스를 생성할 수 있다.

컴파일 시점에서 오류를 찾아내기에, any에 비해 오류를 쉽게 포착할 수 있다. 

코드 가독성이 높아진다.

 

 

제네릭으로 함수 만들기

<T> 를 이용해 입력값의 타입을 지정하지 않은 제네릭 타입의 함수

입력값이 문자일 때도 있고, 숫자일때도 있어서 제네릭으로 함수를 만들면 중복 코드가 줄어든다.

// 입력값의 타입을 지정하지 않은 제네릭 타입의 함수
function sort<T> (items:T[]) : T[] {
	return items.sort();
}

const nums: number[] = [1, 2, 3, 4, 5];
const chars: string[] = ["a", "b", "c", "d"];

// 입력값이 문자일 때도 있고, 숫자일때도 있어서 제네릭으로 함수를 만들면 중복 코드가 줄어든다.
sort<number>(nums);
sort<string>(chars);

 

 

제네릭으로 클래스 만들기

Queue 클래스를 제네릭 타입으로 선언한 다음, numberQueue 인스턴스를 생성할 시점에 숫자타입으로 지정한다.

Array.shift()는 배열을 왼쪽으로 한칸 이동하는 것으로, 결과적으로는 맨 앞에 인자가 제거된다.

 

* protected 접근제어자를 이용해 직접 접근을 막는다.

오직 push나 pop 같은 클래스 내의 메서드를 통해 data 변수에 접근 가능하다.

class Queue<T> {
    protected data: Array<T> = [];
    
    push(item: T) {
        this.data.push(item);
    }
    
    pop() : T | undefined {
        return this.data.shift();
    }
}

// 숫자 타입으로 Queue 클래스를 선언
const numberQueue = new Queue<number>();

numberQueue.push(0); // 잘 동작함
numberQueue.push("1"); // 의도하지 않은 실수 사전검출
numberQueue.push(+"1"); // 컴파일 오류

 

 

 

참고

https://typescript-kr.github.io/pages/generics.html

 

TypeScript 한글 문서

TypeScript 한글 번역 문서입니다

typescript-kr.github.io

 

 

 

 


Union 유니언 타입

 

 

유니언 타입

OR 연산자 ( | ) 를 이용해 타입을 여러개 선언하는 방식이다.

제네릭 타입처럼 여러개의 타입을 사용할 수 있다는 점에서 비슷하지만, 

다른 점은 각각의 타입들의 고유 메서드를 사용할 수 없다.

 

예를 들면,

아래 예시처럼 숫자는 length 메서드를 사용할 수 없다.

타입들이 모두 공통적으로 사용가능한 메서드가 아닌 이상 오류가 발생한다.

const printMessage = (message: string | number) => {
	return message;
}

const message1 = printMessage(1234);
const message2 = printMessage("hello world");

message1.length // 오류 발생!!!

 

반면에 제네릭은 어떤 메서드도 사용 가능하다.

코드를 실행할 때 타입을 string으로 지정해주기 때문에 string에서 쓸 수 있는 메서드(length)들은 모두 사용 가능하다.

const printMessage = (message: T) => {
	return message;
}

const message1 = printMessage <number> (1234);
const message2 = printMessage <string> ("hello world");

message2.length // 오류가 발생하지 않는다.

 

 

참고: 더 공부해야할듯.

https://typescript-kr.github.io/pages/unions-and-intersections.html

 

TypeScript 한글 문서

TypeScript 한글 번역 문서입니다

typescript-kr.github.io

 

반응형
반응형

인터페이스

 

인터페이스 (Interface)

상호간에 정의한 규칙, 약속을 의미하며, 변수, 함수, 클래스에 타입을 체크하기 위해 사용한다.

정의된 인스턴스는 직접 생성될 수 없는 추상클래스이며, 인스턴스 내에 정의된 메소드 역시 추상메소드이다.

ES6는 인터페이스를 지원하지 않지만 타입스크립트는 인터페이스를 지원한다.

 

 

인터페이스를 사용하는 이유

프로젝트 외부에서 사용하는 코드의 계약을 정의하는 강력한 방법이다.

타입의 이름을 짓고 코드 안의 계약을 정의한다.

  • 객체의 스펙 (속성과 속성의타입)
  • 함수의 파라미터
  • 함수의 스펙(파라미터, 반환타입)
  • 배열과 객체에 접근하는 방식
  • 클래스

 

인터페이스 예제

// 인터페이스의 정의
interface Todo {
  id: number;
  content: string;
  completed: boolean;
}

// 변수 todo의 타입으로 Todo 인터페이스를 선언하였다.
let todo: Todo;

// 변수 todo는 Todo 인터페이스를 준수하여야 한다.
todo = { id: 1, content: 'typescript', completed: false };

인터페이스에서 정의한 프로퍼티 값을 누락하거나, 정의하지 않은 값을 인수로 전달(초과 프로퍼티)하면

타입스크립트에서는 컴파일 에러가 발생한다. 즉, 인터페이스는 타입을 체크하기 위해 사용된다.

 

 

 


Properties 프로퍼티

 

 

 

인터페이스의 Properties 프로퍼티

1. 컴파일러는 프로퍼티의 두가지 요소를 검사한다.

  • 필수요소 프로퍼티의 유무
  • 프로퍼티의 타입

2. 예약어로 프로퍼티를 세밀하게 컨트롤할 수 있다.

  • ? (Optional Properties)  : 인터페이스의 프로퍼티는 반드시 구현되어야 하지만, ?를 이용한 선택적 프로퍼티로 선언된 경우에는 생략하여도 에러가 발생하지 않는다.
interface SquareConfig {
  color?: string;
  width?: number;
}
 
function createSquare(config: SquareConfig): { color: string; area: number } {
  let newSquare = { color: "white", area: 100 };
  if (config.color) {
    newSquare.color = config.color;
  }
  if (config.width) {
    newSquare.area = config.width * config.width;
  }
  return newSquare;
}
 
let mySquare = createSquare({ color: "black" });
  • readonly(Readonly properties) : 프로퍼티 이름 앞에 readonly 키워드를 붙이면, 객체가 처음 생성될 때만 값을 설정할 수 있고 그 이후 재할당이 불가능하다. 
interface Point {
  readonly x: number;
  readonly y: number;
}

let p1: Point = { x: 10, y: 20 };
p1.x = 5; // error!

 

 

 

 


인터페이스 타입

 

함수, 클래스 인터페이스

타입스크립트에서 인터페이스는 함수, 클래스에서 사용이 가능하다.

 

함수의 타입을 지정하는 인터페이스

올바른 함수의 타입검사를 위해 아래와 같이 사용할 수 있다. 매개변수의 이름은 같을 필요 없다.

// 입력 인자는 string, string  출력 인자는 boolean 임을 지정하는 함수 인터페이스
interface SearchFunc {
    (source: string, subString: string): boolean;
}
// 함수의 타입을 함수인터페이스로 지정함.
let mySearch: SearchFunc;

// 입력값과 출력값의 형식은 인터페이스와 동일해야 한다.
mySearch = function(src: string, sub: string): boolean {
    let result = src.search(sub);
    return result > -1;
}

 

클래스의 타입을 지정하는 인터페이스

클래스가 특정 통신 프로토콜을 충족하도록 명시적으로 강제한다.

// 날짜형태의 프로퍼티가 1개 있는 인터페이스
interface ClockInterface {
    currentTime: Date;
    setTime(d: Date): void; // 추상메서드로 인터페이스를 상속받은 클래스에서 정의되어야 함.
}

// 인터페이스를 상속받은 클래스는 반드시 인터페이스 내에 있는 프로퍼티+메서드를 포함한다.
class Clock implements ClockInterface {
    currentTime: Date = new Date();
    
    setTime(d: Date) {
        this.currentTime = d;
    }
    constructor(h: number, m: number) { }
}

 

 

인터페이스 확장

클래스처럼 인터페이스가 인터페이스를 상속받아 확장할 수 있다.

상속받은 인터페이스가 여러개이면, 각 인터페이스들의 속성값들을 모두 포함하여 선언해야 한다.

interface Shape {
    color: string;
}

// 인터페이스가 인터페이스를 상속받음
interface Square extends Shape {
    sideLength: number;
}

let square = {} as Square;
square.color = "blue";
square.sideLength = 10;
interface Shape {
    color: string;
}

interface PenStroke {
    penWidth: number;
}

// 인터페이스가 인터페이스 여러개를 상속받음
interface Square extends Shape, PenStroke {
    sideLength: number;
}

let square = {} as Square;
square.color = "blue";
square.sideLength = 10;
square.penWidth = 5.0;

 

하이브리드 타입

자바스크립트의 유연하고 동적인 타입특성에 따라 인터페이스 역시 여러가지 타입을 조합할 수 있다.

함수타입이면서 객체타입을 정의할 수 있는 인터페이스를 구현할 수 있다.

interface Counter {
    (start: number): string;
    interval: number;
    reset(): void;
}

function getCounter(): Counter {
    let counter = (function (start: number) { }) as Counter;
    counter.interval = 123;
    counter.reset = function () { };
    return counter;
}

// c는 함수타입을 수행하기도 하고, 객체타입을 수행하기도 한다.
let c = getCounter();
c(10);
c.reset();
c.interval = 5.0;

 


인터페이스를 활용한 디자인패턴

전략 패턴

객체가 할 수 있는 행위들을 전략으로 만들어 두고, 

동적으로 행위의 수정이 필요한 경우 전략을 바꾸는 것만으로 수정이 가능하도록 만드는 패턴이다.

 

즉, 자판기 결제 방법을 전략(현금결제, 카드결제... 등)으로 만들어두고, 결제방식의 수정이 필요한 경우 전략을 바꾸는 것만으로 수정이 가능해진다.

 

- 결제전략에 필요 메서드를 포함한 인터페이스

interface PaymentStrategy {
  pay(): void;
}

 

- 결제 방식에 따른 전략을 클래스로 정의 ( 인터페이스의 추상메서드는 여기서 구현되어져야 함) 

- 자판기 클래스 생성. 전략을 주입하는 setPaymentStrategy 메서드를 정의한다.

- 추후 결제전략이 바뀔 경우, 이 메서드를 이용해 전략을 바꾸면 된다.

class VendingMachine {
  private paymentStrategy: PaymentStrategy;

  // 전략 변경 메서드
  setPaymentStrategy(paymentStrategy: PaymentStrategy) {
    this.paymentStrategy = paymentStrategy;
  }

  // 바뀐 전략에 따라 호출되는 메서드도 달라짐.
  pay() {
    this.paymentStrategy.pay();
  }
}

 

- 자판기 선언 후 현금결제 전략 주입 후 출력해보고, 카드결제 전략 주입 후 출력해보기

const vendingMachine = new VendingMachine();

vendingMachine.setPaymentStrategy(new CashPaymentStrategy());
vendingMachine.pay(); // cash pay

vendingMachine.setPaymentStrategy(new CardPaymentStrategy());
vendingMachine.pay(); // card pay

 

 

 

 

 

참고

https://poiemaweb.com/typescript-interface

 

TypeScript - Interface | PoiemaWeb

인터페이스는 일반적으로 타입 체크를 위해 사용되며 변수, 함수, 클래스에 사용할 수 있다. 인터페이스는 여러가지 타입을 갖는 프로퍼티로 이루어진 새로운 타입을 정의하는 것과 유사하다.

poiemaweb.com

 

https://typescript-kr.github.io/pages/interfaces.html

 

TypeScript 한글 문서

TypeScript 한글 번역 문서입니다

typescript-kr.github.io

 

반응형
반응형

OOP

프로그램 개발을 유연하게 하고, 변경이 용이하다

개발과 보수가 간편해진다.

직관적인 코드분석이 가능해진다.

 

강한 응집력과 약한 결합력 지향

응집력은 같은 로직은 한곳으로 응집되며, 각각의 로직들은 서로 분리되어 결합이 약해지는 것이 중요하다.

 

클래스 요소

  • 멤버
  • 필드
  • 생성자 메소드

 

인스턴스

new 연산자에 의해 생성된 객체를 의미한다.

 

예제 코드

class Person {
  name: string;

  constructor(name: string) {
    this.name = name;
  }

  // "my name is" + this.name을 출력하는 say() 함수를 완성하세요.
  say() {
    console.log(`my name is ${this.name}`);
  }
}

// Person 클래스의 인스턴스를 생성하여 "my name is 엘리스"가 출력되도록 say() 함수를 호출하세요.
const p = new Person('엘리스');
p.say();

class Person은 클래스이며, const p는 인스턴스이다.

 

 

 

접근제어자 

속성 또는 메소드로의 접근을 제한하기 위해 사용한다.

  • public : 자유롭게 접근 가능.
  • protected : 멤버가 포함된 클래스와, 그 하위 클래스를 제외한 외부에서의 접근을 막는다. 
  • private : 클래스 외부에서의 접근을 막는다. 내부에서 접근 가능.

 

 

상속

상위 클래스의 기능을 재사용, 확장하여 새로운 클래스를 만들 수 있다.

  • extends 키워드를 이용하면 상위 클래스에서 하위 클래스를 파생시켜 만들 수 있다.
  • Animal이 상위 클래스(기초 클래스)라고 하고 Cat 또는 Dog 클래스는 하위 클래스이다. 

 

 


 

 

접근제어자

  • 상위 클래스 Animal을 상속받아 하위 클래스 Dog가 생겨났다.
  • Dog 클래스에서 super( ) 연산을 통해 상위 클래스 Animal의 name 변수에 접근하려고 한다.
  • 이때 name은 public 또는 protected 여야 하위 클래스에서 상위 클래스의 변수로 접근이 가능하다. 
  • 만약 private로 지정하고자 한다면, name에 접근할 수 있는 메서드(getter와 setter)를 만들어서 사용하면 된다.

 

class Animal {
  // 코드가 정상 동작 할수 있게 접근제어자를 수정해주세요.
  protected name: string

  constructor(name: string) {
    this.name = name;
  }
}

class Dog extends Animal {
  constructor(name: string) {
    super(name);    // 인자가 여러개면, super(name, age, email) 이런식으로 사용
  }
  
  makeSound() {
    console.log(this.name + " 멍멍!!")
  }
}

const dog = new Dog("진돗개")
dog.makeSound() // 진돗개 멍멍!! 출력

 

getter / setter

클래스 속성에 직접 접근하여 값을 수정하거나 읽는 것을 막기 위한 것이다.

속성에 직접 접근하여 수정하면 데이터 무결성이 깨질 수 있다. (캡슐화)

 

 

readonly

속성을 읽기 전용으로 설정해 변경할 수 없게 만든다.

선언될 때나 생성자에서 값을 설정하면 이후 수정할 수 없다.

 

static

각 인스턴스가 아닌 클래스 자체에서 보이는 전역 멤버를 생성한다.

범용적으로 사용되는 값에 static을 설정한다.

클래스 명 앞에 static 키워드를 붙여 static 멤버에 접근할 수 있다.

ES6에서는 메소드 전용속성에는 선언이 안되었으나 타입스크립트에서는 사용할 수 있다.

 

 

origin을 static으로 선언한 결과, 클래스 외부에서 origin 값을 변경할 수 있게 됨.

class Grid {
  // origin 필드를 전역 멤버로 선언하기 위해 static 사용
  static origin = { x:0, y:0 }
  
  calculateDistance(): void {
    console.log(Grid.origin.x * Grid.origin.y);
  }
}

const grid = new Grid();

// 외부에서 Grid origin 값 변경
Grid.origin = { x:3, y:3 } 
grid.calculateDistance(); // "9" 출력

 

 

 


 

추상 클래스

추상 클래스는 다른 클래스들이 파생될 수 있는 기초 클래스이다.

  • 직접 인스턴스화 할 수 없다.
  • abstract 키워드는 추상 클래스는 추상 메서드를 정의하는 데에 사용된다.
  • 추상 메소드는 클래스에 구현되어 있지 않고, 반드시 파생된 클래스에서 구현해야 한다.

 

템플릿 메서드 패턴

추상클래스를 활용한 디자인패턴이다.

  • 프로그램의 일부분을 서브 클래스로 캡슐화하여 전체 구조를 바꾸지 않고 특정 단계의 기능을 바꾸는 패턴.
  • 전체적인 알고리즘은 상위 클래스에서 구현하고, 다른 부분(세밀한 부분)은 하위 클래스에서 구현한다.
  • 전체 구조는 유사하지만 부분적으로 다른 구문으로 구성된 메소드의 코드 중복을 최소화할 수 있다.

 

예제 코드

  • 추상클래스 Animal은 인스턴스화 불가능하므로, extends로 상속된 하위 클래스 Dog를 이용해 인스턴스화 할 수 있다.
  • 추상메서드 makeSound( ) 는 하위 클래스에서 반드시 구현되어져야 한다.
  • name은 protected 접근자를 사용하므로, super를 통해 접근할 수 있다.
abstract class Animal {
  protected name: string;

  constructor(name: string) {
    this.name = name;
  }

  abstract makeSound(): void;
}

class Dog extends Animal {
  // constructor를 구현
  constructor(name: string) {
    super(name);
  }
  // 추상메소드 makeSound()를 Dog 클래스 내부에서 구현
  // makeSound() 메소드에 console.log를 구현
  makeSound(): void {
    console.log(this.name + " " + '멍멍!!');
  }
}

// 클래스 name필드에 값 "진돗개"를 할당해주세요
const dog = new Dog('진돗개');
dog.makeSound(); // 진돗개 멍멍!!

 

 

 

 

 

 

 

 

반응형
반응형

Utility tyles

타입스크립트는 공통타입 변환을 용이하게 하기 위해 유틸리티 타입을 제공한다.

유틸리티 타입은 전역으로 사용 가능하다.

 

(1) Partial <T>

프로퍼티(속성)을 선택적으로 만드는 타입을 구성한다.

주어진 타입의 모든 하위 타입 집합을 나타내는 타입을 반환한다.

interface Todo {
  title: string
  description: string
}

// obj매개변수 타입에 Partial Utility types을 추가
function updateTodo(obj: Partial<Todo>) { 
  return obj;
}

// updateTodo는 Todo 인터페이스를 객체로 받아와야하는데, 
// result에서 넘겨주는 값은 일부 (2개중 1개)만 넘기기 때문에 Partial<Todo>를 하지 않으면 오류
const result = updateTodo({
  title: "title",
})

console.log(result); // { title: 'title' } 출력

updateTodo function 함수는 Todo 인터페이스를 객체로 받아와야하는데, 
result에서 넘겨주는 값은 일부 (2개중 1개)만 넘기기 때문에 Partial<Todo>를 하지 않으면 오류가 발생한다.

 

 

(2) Readonly <T>

프로퍼티(속성)을 읽기전용(read only) 으로 설정한 타입을 구성한다.

 

(3) Record <T>

프로퍼티의 집합 K로 타입을 구성한다.

타입의 프로퍼티들을 다른 타입에 매핍시키는 데 사용한다.

 

(4) Pick <T, K>

프로퍼티 K의 집합을 선택해 타입을 구성한다.

interface Todo {
  title: string
  description: string
  completed: boolean
}

// Pick을 이용해 title 프로퍼티를 포함
type TodoPreview = Pick<Todo, "title">

const todo: TodoPreview = {
  title: "Clean room"  
}

 

 

(5) Omit <T, K>

모든 프로퍼티를 선택한 다음, K를 제거한 타입을 구성한다.

interface Todo {
  title: string
  description: string
  completed: boolean
}

// Omit을 이용해 description 프로퍼티를 제외
type TodoPreview = Omit<Todo, "description">

const todo: TodoPreview = {
  title: "Clean room",
  completed: false,  
}

이 경우에 Partial 타입을 사용해도 됨.

 

 

 

(6) Exclude <T, U>

T에서 U에 할당할 수 있는 모든 속성을 제외한 타입을 구성한다.

 

(7) Extract <T, U>

T에서 U에 할당할 수 있는 모든 속성을 추출하여 타입을 구성한다.

 

(8) NonNullable <T>

null 과 undefined를 제외한 타입

 

(9) Parameters <T>

함수 타입 T의 매개변수 타입들의 튜플 타입을 구성한다.

 

(10) ConstructorParameters <T>

생성자 함수 타입의 모든 매개변수 타입을 추출한다.

모든 매개변수 타입을 가지는 튜플 타입(T가 함수가 아닌 경우 never)을 생성한다.

 

(11) ReturnType <T>

함수 T의 반환타입으로 구성된 타입을 생성한다.

 

(12) Required <T>

T의 모든 프로퍼티가 필수로 설정된 타입을 구성한다.

 

 

 


함수

 

매개변수: 함수를 정의할 떄 사용되는 변수를 의미한다. 인자 값 또는 파라미터 라고도 한다.

인수: 함수를 호출할 때 사용되는 값을 의미한다.

 

function add(x, y) {
	return x+y;
}

add(2, 5);

여기서 x와 y는 파라미터(인자)라고 하고, 2와 5는 인수값이라고 한다.

 

 

 

일급 객체 (First-class object)

자바스크립트와 타입스크립트의 함수는 일급객체이다.

다른 객체들에 일반적으로 적용가능한 연산을 모두 지원하는 객체를 일급 객체라고 한다.

  • 다른 함수에 매개변수로 제공할 수 있다.
  • 함수에서 함수를 반환하는게 가능하다.
  • 변수에 함수 할당이 가능하다.
let elice = function() { return "coding"; };
console.log(elice()); // "coding"

함수를 정의해 변수에 저장하고, 변수를 호출하면 함수실행 결과가 반환되는 것을 확인할 수 있다.

 

 

 

 

함수 선언 방법

함수 선언식

함수 표현식

화살표 함수 표현식

단축형 화살표 함수 표현식

함수 생성자 (new 사용. 잘 쓰이지 않음)

 

 

타입 추론(Contextual Typing)

방정식의 한쪽에만 타입이 있더라도 반대쪽 타입을 추론할 수 있다.

이를 통해 타입을 유지하기 위한 노력을 줄일 수 있다.

function add(a: number, b: number) {
    const res = a + b; 
    return res.toString();
}

res 변수는 number이고,

return 반환 값은 string이라는 것이 명백하기 때문에 function의 반환값을 따로 타입을 명시하지 않아도 된다.

 

 

반응형
반응형

타입스크립트 필요성

타입을 명시하지 않고 사용하는 var, let은 변수가 선언되는 과정에서 타입이 지정된다. (동적 타이핑)

이로 인해, 타입 에러와 같은 실수가 있어도 컴파일 단계에서 확인이 어렵다.

 

타입스크립트를 이용한다면,

타입에러를 런타임 단계까지 가지 않고도 컴파일 단계에서 미리 확인하고 고칠 수 있게 된다.

 

 

 

타입스크립트 Type

(1) primitive type 기본형: 값을 저장하는 자료형

  • string
  • boolean
  • number
  • null
  • undefined
  • symbol (es6에서 추가됨)
// 문자형
let str: string = "hi";

// 불대수
let isTrue: boolean = true;

// 숫자
let decimal: number = 6;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;

// null은 object
let n: null = null;

// undefined는 암것도 아님 
let ud: undefined = undefined;

자료형 간 관계성

null === undefined // false
null == undefined // true (wow)

null === null // true
nul == null // true

!null // true

// null은 연산가능, undefined는 연산안됨
isNan(1+null) // false
inNan(1+undefined) // true

 

(2) reference type 참조형

  • object
  • array
  • function
// 변수 o의 타입은 object
// 함수 create의 타입은 void()
function create(o:object) : void(){
	// 코드 작성
}

// 참조형
create({prop: 0}) // 성공
create([1, 2, 3]) // 성공

// 기본형
create("string")  // 실패
create(false)     // 실패
create(42)        // 실패
create(null)	  // 실패
create(undefined  // 실패
let arr: number[] = [1, 2, 3]
let arr: Array<number> = [1, 2, 3]

 

 

(3) 타입스크립트 추가된 자료형

  • tuple
  • enum
  • any
  • void
  • never

 

 

Enum

특정 값(상수)들의 집합

인스턴스 생성, 상속을 방지하여 상수값의 타입안정성이 보장된다.

// enum 선언
enum Car { 
    BUS = "bus", 
    TAXI = "taxi", 
    SUV = "suv" 
}

// enum Car를 이용해서 taxi값을 할당
const taxi:Car = Car.TAXI;
console.log(taxi); // TAXI 출력

 

 


함수의 매개변수 사용법 예제

 

 

addTwo 함수의 구조를 확인하세요. 인자로 건네받은 두 개의 number 타입 변수를 더해서 반환해줍니다.

function addTwo(a: number, b: number): number {
    return a + b;
}

console.log(addTwo(2, 3))

 

?를 사용

선택적 매개변수를 사용해 한 개 또는 두 개의 인자를 입력받는 addOneOrTwo 함수를 만드세요.
인자가 한 개라면 입력받은 인자를 그대로 반환하세요. 인자가 두 개라면 두 인자를 더해서 반환하세요.

// 한 개의 매개변수가 들어올 수도 있고, 두 개의 매개변수가 들어올 수도 있습니다.
// ?를 사용하는 것을 제외하면, 위 함수와 동일하게 작성합니다!
function addOneOrTwo(a: number,  b?: number): number {
    if (b === undefined) return a
    return a+b
}

console.log(addOneOrTwo(5, 10))
console.log(addOneOrTwo(10))

 

초기화 매개변수를 사용해 한 개 또는 두개의 인자를 입력받는 addDefault 함수를 만드세요.
인자가 한 개라면 입력받은 값에 10을 더해서 반환하세요. 인자가 두 개라면 두 인자를 더해서 반환하세요.

function addDefault(a: number, b?: number) {
    if (b === undefined) return (a+10)
    return a+b
    
}
console.log(addDefault(3)) // return 13
console.log(addDefault(12, 15))

 

... rest operation와 reduce 사용

나머지 매개변수를 사용해 두 개 이상의 인자를 입력받는 addTwoOrMore 함수를 만드세요.
입력받은 인자를 모두 더해서 반환하세요.

// // JS도 가변인자 (나머지 매개변수)를 갖고 있어요.
// // 워낙 유용하다보니, 많이 사용했을 것 같지만, 한 번 더 연습해 봅시다.
function addTwoOrMore(...args: number[]): number {
    return args.reduce((total:number, now: number) => total + now)
}

console.log(addTwoOrMore(2, 1))
console.log(addTwoOrMore(8, 8, 6, 1, 9, 6))
반응형
반응형

 

ES6

자바스크립트를 표준화하기 위해 만들어진 스크립트 프로그래밍 언어

 

 

 

1.  let, const, var

기존 변수 선언 방식

var 재정의 가능하고 재선언도 가능하다. 단점은 코드 관리 측면에서 let에 비해 부적합함.

 

ES6 변수 선언 방식

let 가변변수로 재정의가 가능하지만 재선언은 불가능

const 불변변수로 재선언과 재정의 모두 불가능합니다.

var x = 2
let y = 2;
const z = 2;

// 재정의
x = 4; // posible
y = 4; // posible
z = 4; // error

// 재선언
var x = 3 // posible
let y = 3; // error
const z = 3; // error


document.write(x);
document.write(y);
document.write(z);

 

 


2. 모듈화 Import - Export

모듈

프로젝트 규모가 커질수록 관리하기 편하게 모듈화 한다.

여러 기능들에 관한 코드가 모여있는 하나의 파일로 다음과 같은 것들을 위해 사용한다.

 

모듈화의 장점

- 유지보수성: 모듈화되면 의존성이 줄어들어, 개선하거나 수정할 때 편하다.

- 네임스페이스화: 전역변수가 저장된 전역공간과 분리되어 저장됨.

- 재사용성: 똑같은 코드를 반복하지 않고 모듈을 불러다 사용할 수 있다.

 

 

모듈화 적용하기

moduleA.js : default export 사용해서 내보낸 모듈A

const A = () => {};
export default A;

moduleB.js :  named export로 내보낸 모듈B는 사용할 때 중괄호 { }로 불러야 함.

export const B = () => {};

index.js

import A from 'moduleA';
import { B } from 'moduleB';

 

 


3. 템플릿 리터럴

 

Template literals
템플릿 리터럴은 내장된 표현식을 허용하는 문자열 리터럴로 런타임 시점에 일반 자바스크립트 문자열로 처리/변환된다.
표현식/문자열 삽입, 여러 줄 문자열, 문자열 형식화, 문자열 태깅 등 다양한 기능을 제공
프론트엔드에서HTML을 데이터와 결합해서 DOM을 다시 그려야 하는 일이 빈번하기 때문에, 템플릿을 좀 더 쉽게 편집하고 작성해야 할 필요성으로 등장하였다.

 

기존 문자열 사용 방식

+ 기호 사용

 

ES6 문자열 사용 방식

템플릿 리터럴은 작은따옴표(')나 큰따옴표(") 대신 백틱(`)(grave accent)로 감싸준다.

$와 중괄호{}를 사용하여 표현식을 표기할 수 있다.

var variable = "변수";

console.log(`이건 ${variable}입니다.`);

 

* enter 줄바꿈 인식함.

* escapte문자 (/) 필요없음.

 


4. 화살표 함수

기존 함수 선언 방식

function 함수 명(인자) {
	// 코드 선언

}

ES6 함수 선언 방식 

(1) 화살표 함수(arrow function) 

함수 표현식(ES5)보다 단순하고 간결한 문법으로 함수를 만들 수 있는 방법

// ES5
var pow = function (x) { return x * x; };
 
// ES6
const pow = x => x * x;

 

화살표 함수 선언 방식

    () => { ... } // 매개변수가 없을 경우
     x => { ... } // 매개변수가 한 개인 경우, 소괄호를 생략할 수 있다.
(x, y) => { ... } // 매개변수가 여러 개인 경우, 소괄호를 생략할 수 없다.

참고 링크

 

 

 

 

this 

 

(1) 기존 일반 함수(ES5) 내에서의 this

일반 함수(ES5)로 정의한 함수 내에서 this는 전역객체를 가리킨다.

아래 코드에서 this.title을 출력하면 window를 this로 참조하기 때문에 group의 title을 못가져 온다.

let group = {
  title: "1모둠",
  students: ["보라", "호진", "지민"],
 
  showList() {
    this.students.forEach( // this === group
      function(student) { alert(this.title + ': ' + student) } // this ==== window
    );
  }
};
 
group.showList();
 
// undefined : 보라
// undefined : 호진
// undefined : 지민

(2) 화살표 함수(ES6) 내에서의 this

화살표 함수로 정의된 스코프 내에는 this가 존재하지 않는다.

따라서 this로 접근하면 상위 스코프를 가리킨다. 

아래 코드에서 this.title을 출력하면 상위 this(여기선 group)를 참조하기 때문에 group의 title을 가져올 수 있게 된다.

/* 화살표 함수로 쓸 경우 */
/* 화살표 함수의 this는 상위의 this를 그대로 가져온다. */
 
let group = {
  title: "1모둠",
  students: ["보라", "호진", "지민"],
 
  showList() {
    this.students.forEach( // this === group
      student => alert(this.title + ': ' + student) // this === group
    );
  }
};
 
group.showList();
 
// 1모둠 : 보라
// 1모둠 : 호진
// 1모둠 : 지민

참고링크

 

 


5. 클래스

 

기존 클래스 선언 방식: function

class가 없을 땐 function 키워드와 prototype 속성을 이용해 클래스를 구현해야 했다.

function Model(name, age) {
	this.name = name
    this.age = age
}

// class가 없을 땐 prototype으로 클래스를 구현해야 했다.
Model.prototype.getInfo = function() {
	console.log(this.name, this.age)
}

// 선언은 new로
var model = new Model('elice', 5)
model.getInfo()

 

 

ES6 클래스 선언 방식: class

 

Class  

Class 등장 이후, 프로토타입 없이도 클래스 내부에 변수 뿐만 아니라 함수도 선언 가능해졌다.

아래 코드는 Model이라는 클래스를 생성하고, 생성자(Constructor)로 정의한다.

또한 클래스 내에 정의한 메서드 getInfo()는 프로토타입에 저장된다.

// class 내부에 변수 뿐만 아니라 함수도 선언 가능해졌다.
class Model {
    constructor(namem age) { 
        this.name = name; 
        this.age = age;
    }
    getInfo() { 
    	console.log(this.name, this.age);
    }
}

// 선언은 new로
const model = new Model('elice', 5);
model.getInfo();

 참고 링크

 

 


6. forEach ( ) 

forEach ( 함수 )

반복작업을 가능하게 한다.

즉, 배열 요소 각각에 대해 함수를 반복실행할 수 있다.

 

기존 for 반복문

var fruits = ["apple", "orange", "cherry"];

function myFunction(item, index) {
  document.write(index + ":" + item + "<br>");
}

for (i = 0; i < 3; i++) {
  document.write(i);
  document.write(":" + fruits[i] + "<br>");
}

// 출력
// 0:apple
// 1:orange
// 2:cherry

 

arr.forEach(function() {  }) 사용

var fruits = ["apple", "orange", "cherry"];

function myFunction(item, index) {
  document.write(index + ":" + item + "<br>");
}

fruits.forEach( function (item, index) {
    myFunction(item, index)
})

 

arr.forEach(화살표 함수) 사용

var fruits = ["apple", "orange", "cherry"];

function myFunction(item, index) {
  document.write(index + ":" + item + "<br>");
}

fruits.forEach((item, idx) => {
    myFunction(item, idx)
})

 


7. map( ) 

map( ) 

배열을 변형하거나 재정렬하는 메서드

 

 

Object.map(함수)

var persons = [
  { firstname: 'Malcom', lastname: 'Reynolds' },
  { firstname: 'Kaylee', lastname: 'Frye' },
  { firstname: 'Jayne', lastname: 'Cobb' },
];

function getFullName(item) {
  var fullname = item.firstname + ' ' + item.lastname + '<br>';
  document.write(fullname);
}

persons.map(getFullName);

// 출력
// Malcom Reynolds
// Kaylee Frye
// Jayne Cobb

Array.map(함수)

var numbers = [4, 9, 16, 25];
var x = numbers.map(Math.sqrt);
document.write(x);

// 출력
// 2,3,4,5

 

 

 


8. reduce ( ) 

 

reduce

forEach 처럼 반복작업을 한다는 점은 비슷하나, 배열을 기반으로 값 하나를 도출할 때 사용한다. 

map은 각각의 요소를 변형시킨다면, reduce는 배열 자체를 변형시킨다.

 

Array. reduce(누적값, 현잿값, 인덱스, 요소) => { return 결과 }, 초기값);

함수의 인자는 총 4개를 가진다.

1. 누산기(Accumulator)

2. 현재값(Current)

3. 현재 인덱스(Index)

4. 원본배열(Source)

 

var numbers = [175, 50, 25];
document.write(numbers.reduce(myFunc));

function myFunc(total, num, index, arr) {
    document.write(total+"<br>")
    document.write(num+"<br>")
    document.write(index+"<br>")
    document.write(arr+"<br>")

    document.write("<br>")
  return total - num;
}




// 출력

// 175
// 50
// 1
// 175,50,25

// 125
// 25
// 2
// 175,50,25

// 100

 

 

 

 


9. destructing

 

객체 내 변수를 쉽게 꺼내는 방법

 

기존

// 객체의 경우
var obj = {name: 'elice', age:5};
var name = obj.name;
var age = obj.age;

//배열의 경우
var arr = ['some', 'values'];
var first = arr[0];
var second = arr[1];

 

ES6

// 객체일 때
const obj = {name: 'elice', age: 5};

const {name, age} = obj;
const {name:n1, age:a1} = obj; // 이름 바꿔서 선언하고자 할 때


// 변수일 때
const arr = ['some', 'values'];
const [first, second] = arr;

 

 

반응형

+ Recent posts