TIL 210622

jm·2021년 6월 22일
0

공부한 내용

JS 5. 함수

https://youtu.be/e_lU39U-5bQ

함수는 프로그램 안에서 각각의 작은 단위의 기능들을 수행함

  • 언어 자체에 존재하는 함수를 쓸 때 또는 API를 쓸 때 함수의 이름을 보고 기능을 유추함
    → 전달해야 하는 파라미터가 무엇인지, 어떤 값이 리턴되는지 인터페이스를 보고 예상함
  • 프로그램을 구성하는 가장 기본적인 빌딩 블럭이며 여러번 재사용이 가능
  • 대체적으로 한 가지의 태스크나 어떤 값을 계산하기 위해 쓰임

Function declaration

function name(param1, param2) { body... return; }
// function 입력, 함수 이름 지정(파라미터 나열) {함수 안의 기본적인 비즈니스 로직 작성 ... 리턴;}
  • 하나의 함수는 한 가지의 일만 해야함

  • 함수는 동작하는 것이기 때문에 함수의 이름은 커맨드 형태 혹은 동사 형태로 정해야 함
    → e.g. createCardAndPoint -> createCard, createPoint

  • JS에서 함수는 오브젝트로 간주
    → 함수를 변수에 할당 할 수 있음, 파라미터로 전달이 됨, 함수 리턴 가능

function log(message) {
  console.log(message);
}
log('Hello');
log(1234) 

Parameters

primitive 타입 같은 경우 메모리에 값이 그대로 저장되어 있기 때문에 값이 전달 되고, 오브젝트는 메모리에 레퍼런스가 저장되어 있기 때문에 레퍼런스가 전달되어 짐

function changeName(obj) {
  obj.name = 'coder';
}

const ellie = { name: 'ellie' };
changeName(ellie);
console.log(ellie);

// {name: "coder"}

Default Parameters

파라미터 옆에 원하는 디폴트 값을 지정해 놓으면 사용자가 파라미터를 전달하지 않을 때 값이 대체 되어 사용됨

function showMessage(message, from = 'unknown') {
  console.log(`${message} by ${from}`);
}
showMessage('Hi!')

Rest parameters

...을 작성하게 되면 배열 형태로 전달됨

function printAll(...args) {
  for (let i = 0; i < args.length; i++) {
    console.log(args[1]);
  }
}
printAll('dream', 'coding', 'ellie');

// dream
// coding
// ellie

간략한 코드

for (const arg of args) {
    console.log(arg);
  }

args.forEach((arg) => console.log(arg)); 

Return

함수에서는 파라미터로 값을 전달받아서 계산된 값을 리턴할 수 있음

function sum(a, b) {
  return a + b;
}
const result = sum(1, 2); // 3
console.log(`sum: ${sum(1, 2)}`);

Function Expression

JS에서는 function도 다른 데이터 타입처럼 변수에 할당이 가능하고 그렇기 때문에 함수의 파라미터 인자로도 전달이 되고 함수에 리턴 타입으로도 return이 된다.

const print = function () { // anonymous function
  console.log('print');
};

print(); // print

const printAgian = print;
printAgian(); // print

const sumAgian = sum;
console.log(sumAgian(1,3)); // 4

Callback

function randomQuiz(answer, printYes, printNo) {
  if (answer === 'love ypu') {
    printYes();
  } else {
    printNo();
  }
}

// anonymous function
const printYes = function () {
  console.log('yes'); 
};

// named function
// better debugging in debugger's stack traces
// recursions
const printNo = function print() {
  console.log('no');
};
randomQuiz('wrong', printYes, printNo);  // no
randomQuiz('love you', printYes, printNo); // yes

Arrow function

함수를 간결하게 만들어줌 (anonymous function)

const simplePrint = function () {
  console.log('simplePrint');
};

const simplePrint = () => console.log('simplePrint');

IIFE

함수를 선언함과 동시에 호출

(function hello() {
  console.log('IIFE');
})();

// IIFE

Function declaration과 Function Expression의 차이점

Function Expression은 함수가 할당 된 다음부터 호출이 가능
Function declaration은 hoisted가 되기 때문에 함수가 선언되기 전에 호출이 가능함

JS 6. 클래스

https://youtu.be/_DLhUBWsRtw

연관있는 변수와 함수를 묶어 놓는 컨테이너
ES6에서 도입되었으며 클래스가 도입 되기 전에는 클래스를 정의하지 않고 바로 오브젝트를 만들 수 있었다.

  • 클래스 자체에는 데이터가 없고 틀만 정의함 (한번만 선언)
  • 클래스를 이용해 새로운 인스턴스를 생성하는 것은 오브젝트 이다.
class name { 
	field1;
	field2;
	method(); // method가 없는 클래스는 data class라고 부름
}

클래스 내부에서도 내부적으로 보여주는 변수와 외부적으로 보여지는 변수를 나누어서 캡슐화 라고 함

클래스를 이용해서 상속다형성이 이루어짐

→ 객체지향 언어(object-oriented programming)의 특징

Class declarations

class Person {
  // constructor, 오브젝트를 만들 때 필요한 데이터를 전달함
  constructor(name, age) { 
    // fields
    this.name = name;
    this.age = age; // 데이터 할당
  }
	// methods
  speak() {
    console.log(`${this.name}: hello!`);
  }
}

// 오브젝트 생성
const ellie = new Person('ellie', 20);
console.log(ellie.name); // ellie
console.log(ellie.age); // 20
ellie.speak(); //ellie: hello!

Getter and setters

class User {
  constructor(firstName, lastName, age) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
  }

  get age() {
    return this._age; // call stack 무한반복을 막기 위해 get과 set의 변수 값을 변경해야 함
  }
	// getter를 정의한 순간, this.age는 메모리에 올라간 데이터를 읽어오는 것이 아닌 getter를 호출하게 됨

  set age(value) {
    this._ago = value < 0 ? - : value;
  }
	// setter를 정의한 순간, = age는 바로 메모리의 값을 할당하는 것이 아니라 setter를 호출하게 됨 
} 

const user1 = new User('steve', 'job', -1);
console.log(user1.age);

user1.age이 -1인 것은 말이 안되기 때문에 get을 이용해서 값을 리턴하고 set을 이용해서 값을 설정할 수 있다.

→ 사용자가 get age를 호출하게 되면 this.age를 리턴해야 되고 새로운 value를 받으면 this.age를 value로 설정하게 된다.

Public & Private

public 생성자를 쓰지 않고 필드를 정의하면 외부에서 접근 가능함 ()

private #를 붙이면 클래스 내부에서만 접근이 가능해서 값을 볼 수 있고 변경도 되지만 외부에서는 불가능함

class Experiment {
  publivField = 2;
  #privateField = 0;
}
const Experiment = new Experiment();
console.log(experiment.publivField); // 2
console.log(experiment.privateField); // undefined

Static

오브젝트와 데이터에 상관없이 클래스가 가지고 있는 고유한 값과 이런 데이터에 상관없이 동일하게 반복적으로 사용 되는 메소드가 있을 수 있음

→ Static을 사용하면 오브젝트에 상관없이 클래스 자체에 연결됨

class Article {
  static publisher = 'Dream Coding';
  constructor(articleNumber) {
    this.articleNumber = articleNumber;
  }

  static printPublisher() {
    console.log(Article.publisher);
  }
}

const article1 = new Article(1);
const article2 = new Article(2);
console.log(Article.publisher) // Dream Coding
// publisher는 Article이라는 클래스 자체에 붙어있음 
Article.printPublisher(); // Dream Coding

오브젝트에 상관없이 공통적으로 클래스에서 쓸 수 있다면 Static과 Static method를 이용해서 작성하는 것이 메모리의 사용을 조금 줄여줌

상속 & 다형성

공통적으로 쓰이는 속성 값을 계속 재사용하면 유지보수하기 쉬워짐

class Shape {
  constructor(width, height, color) { 
    this.width = width;
    this.height = height;
    this.color = color;
  }
	draw() {
    console.log(`drawing ${this.color} color!`);
  }

  getArea() {
    return width * this.height;
  }
}

// 새로운 클래스를 만들고 싶을 때 extands를 사용해서 Shape를 연장함(상속)
class Rectangle extends Shape {}
class Triangle extends Shape {
	// 부모 오브젝트의 함수를 호출하고 재정의한 함수도 호출하려면 super 사용
  draw() {
    super.draw(); 
    console.log('🔺');
  }

	// 필요한 함수만 재정의(오버라이딩)
  getArea() {
    return (this.width * this.height) / 2;
  }
}

const rectangle = new Rectangle(20, 20, 'blue');
rectangle.draw();
console.log(rectangle.getArea());

const triangle = new Triangle(20, 20, 'red');
triangle.draw();
console.log(triangle.getArea());

instanceOf

오브젝트는 클래스를 이용해서 만들어진 새로운 인스턴스이다.

→ instanceof를 사용하면 오브젝트가 해당 클래스를 이용해서 만들어진 인스턴스인지 확인하는 방법

console.log(rectangle instanceof Rectangle); // true
console.log(triangle instanceof Rectangle); // false
console.log(triangle instanceof Triangle); // true
console.log(triangle instanceof Shape); // true
  • JS에서 만든 모든 오브젝트 클래스들은 JS에 있는 Object를 상속한 것
console.log(triangle instanceof Object); // true

JS 7. 오브젝트

https://youtu.be/1Lbr29tzAA8

object = { key: value };

오브젝트는 접근할 수 있는 프로퍼티와 그 프로퍼티가 가지고 있는 값으로 이루어짐

literals and properties

primitive type은 변수 하나당 하나의 값만 담을 수 있음

  • 인자가 많아지게 되면 추가해야 하는 것들이 많아짐 → 관리하기 힘듦
const name = 'ellie';
const age = 4;
print(name, age);

// name과 age를 각각 파라미터로 전달해줘야함

오브젝트를 만드는 방법

const obj1 = {}; // object literal
const obj2 = new Object(); // object constructor
  1. object literal
  2. object constructor
    • 오브젝트를 new 라는 키워드를 이용해서 생성하면 오브젝트에서 정리된 constructor가 호출됨
// 오브젝트 화
function print(person) {
  console.log(person.name);
  console.log(person.age);
}

const ellie = { name: 'ellie', age: 4 };
print(ellie);
  • 오브젝트 선언 후에도 프로퍼티를 추가하거나 삭제할 수 있음
// can add properties later
ellie.hasJob = true;
console.log(ellie.hasJob);

// can delete properties later
delete ellie.hasJob;
console.log(ellie.hasJob);

Computed properties

오브젝트의 안에 있는 데이터에 접근하려면 .을 이용함

오브젝트는 프로퍼티를 .을 이용해서 접근이 가능하고 또는 computed property []에서 접근이 가능함

  • 프로퍼티의 키는 반드시 스트링 타입으로 해야함
console.log(ellie.name);
console.log(ellie['name']);

ellie['hasJob'] = true;
console.log(ellie.hasJob)
  • . 코딩할 때 그 키에 해당하는 값을 받아 오고 싶을 때 사용
  • [] 실시간으로 원하는 키의 값을 받아 오고 싶을 때 사용

Property value shorthand

키와 밸류의 이름이 동일하다면 생략할 수 있음

const person1 = { name: 'bob', age: 2 };
const person2 = { name: 'steve', age: 3 };
const person3 = { name: 'dave', age: 4 };

function makePerson(name, age) {
  return {
    name,
    age,
  };
}

const perdon4 = makePerson('ellie', 30 );

Constructor Function

JS 엔진이 알아서 오브젝트를 생성함

function Person(name, age) {
	// this = {};
  this.name = name;
	this.age = age;
	// return this;
}

const perdon4 = new Person('ellie', 30 );

In operater

해당 키를 가진 프로퍼티가 객체 내에 있는지 확인할 때 사용

  • 정의하지 않은 키를 접근하게 되면 undefined이 뜸
console.log('name' in ellie);
console.log('age' in ellie);
console.log('random' in ellie); // 정의하지 않은 키를 사용 -> false 출력
console.log(ellie.random); //정의하지 않은 키에 접근 -> undefined 출력

for in for of

for in

모든 키를 받아와서 처리하고 싶을 때 사용

for (key in ellie) {
  // 'ellie'가 가지고 있는 키들이 블럭을 돌 때 마다 'key'라는 지역변수에 할당이 됨
	console.log(key);
}

// name
// age
// hasjob

for of

오브젝트를 쓰는 것이 아닌 배열리스트를 사용

const array = [1, 2, 4, 5];
for (value of array) {
  console.log(value);
}
// array의 모든 값이 value에 할당 되면서 블럭 안에서 순차적으로 출력하거나 값을 개선할 수 있음
// 1
// 2
// 4
// 5

cloning

오브젝트를 복제하는 방법

const user = { name: 'ellie', age: '20' };
const user2 = user;
user2.name = 'coder';
console.log(user);

// user라는 변수의 레퍼런스에는 'ellie'이라는 값과 '20'을 가지고 있음
// user2의 변수는 user가 할당되어 있기 때문에 동일한 레퍼런스와 값을 가지고 있음
// user2가 가리키고 있는 레퍼런스는 'ellie'를 'coder'로 변경함
// 따라서 user가 가리키고 있는 오브젝트가 'coder'로 변경됨

object.assign

// old way

const user3 = {};
for (key in user) { // name, age
  user3[key] = user[key];
	// user3 프로퍼티의 값은 기존에 있는 user의 값을 가져옴
}
console.log(user3); // {name: 'coder', age: '20'};

const user4 = Object.assign({}, user);
console.log(user4);

객체지향 언어의 특성: 상속, 캡슐화, 다형성 +추상화

역시나 정보처리기사 공부할때 나왔던 개념이다. 근데 이걸 코드로 보니까

함수를 물어봐도 와까라나이
클래스를 물어봐도 와까라나이

그저 울고 있는 아기 코린이가 되었다...

강의 들으면서 모르겠는 부분은 계속 돌려 보고 있는데 쉽지 않다..

0개의 댓글