본문 바로가기

Nodejs

node.js 함수, 객체, 클래스, 상속 (2024-04-19)

node.js

node.js는 JavaScript 런타임 환경으로 서버 애플리케이션을 개발하는데 주로 사용됨

설치
https://nodejs.org/en/

 

Node.js — Run JavaScript Everywhere

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

nodejs.org

 

 

function

더보기
function sum(num1, num2){
    console.log('sum()호출!')
    return num1 + num2; //13
}



const result = sum(10,3);
console.log(result) //sum()호출! 13

console.log('-------------------')

// 함수의 메모리 주소 전달하는 방법
const add = sum;
console.log(sum(10,3)); //sum()호출! 13
console.log(add(10,3)); //sum()호출! 13

console.log('-------------------')

// 함수의 작성팁
// 조건식이 있을 때 조건을 만족하지 않은 경우를 함수 도입부분에서 모두 처리 후 함수를 미리 종료
function print(num){
    if(num<0) return;
    console.log(num);
}

print(10); // 10

print(-5); // 출력 없음

// 매개변수의 기본값은 무조건 undefined
// arguments : 함수의 전달된 인수에 해당하는 값을 array 형태의 객체로 반환
function total(num1, num2){
    console.log(num1);
    console.log(num2);
    console.log('arguments : ', arguments)
    console.log('arguments[0] : ', arguments[0])
    console.log('arguments[1] : ', arguments[1])
    return num1 + num2;
}

console.log(total()); 
/*
 undefined
 undefined
 arguments :  [Arguments] {}
 arguments[0] :  undefined
 arguments[1] :  undefined
 NaN
*/
 
console.log(total(10, 3)); 
/*
 10
 3
 arguments :  [Arguments] { '0': 10, '1': 3 }
 arguments[0] :  10
 arguments[1] :  3
 13
*/

console.log('-------------------')

// callback 함수 활용
const calc_add = (a, b) => a + b;
const calc_multiply = (a, b) => a * b;

console.log(calc_add(10,3)); // 13
console.log(calc_multiply(10,3)); //30


// calculater(num1, num2, action)

function calculater(num1, num2, action){
    if(num1 < 0 || num2 < 0 ) return;   
    const result = action(num1, num2);

    console.log(result);
    return result;
}

calculater(4, 2, calc_add); // 6
calculater(4, 2, calc_multiply); // 8

 

Object

더보기
const Rucy = {
name: '루시', age: 14, 'weight': 3.5, ['height'] : 0.7, ['owner-name'] : '김사과'}


console.log(Rucy.name);
console.log(Rucy.weight);
console.log(Rucy.height);
// console.log(Rucy.owner-name); error
console.log(Rucy['owner-name']);

Rucy.family = '포메라니안'
console.log(Rucy.family);
console.log(Rucy['family']);


console.log(Rucy);

delete Rucy['owner-name'];
console.log(Rucy['owner-name']); // undefined
console.log(Rucy);

console.log('-----------------------');


// 동적으로 프러퍼티에 접근하는 함수
function getValue(obj, key){
    return obj[key];
}
console.log(getValue(Rucy, 'age')); // 14

// 동적으로 요소를 추가하는 함수
function addKey(obj, key, value){
    obj[key] = value;
}
addKey(Rucy, 'owner-name', '김사과');
console.log(Rucy);

// 동적으로 요소를 삭제하는 함수
function delKey(obj, key){
    delete obj[key];
}
delKey(Rucy, 'weight');
console.log(Rucy);

// 객체 생성 함수 만들기

// 좌표 객체 만들기
const x = 0;
const y = 0;

const coord = {x,y}
console.log(coord); // { x: 0, y: 0 }

// 이름, 나이를 전달하여 객체로 만들어주는 함수 만들기
function makeObj(name, age){
    return {name, age};
}
console.log(makeObj('김사과', 20))

// 리터럴 표기법으로 객체 만들기
const apple = {
    name : '김사과',
    emoji : '🍎',
    display : function(){
        console.log(`${this.name}: 🍎`)
    }
}

const banana = {
    name : '반하나',
    emoji : '🍌',
    display: function(){
        console.log(`${this.name} : 🍌`)
    }
}

console.log(apple); // { name: '김사과', display: [Function: display] }
apple.display(); // 김사과: 🍎

console.log(banana); // { name: '반하나', display: [Function: display] }
banana.display();

// 문제
// Fruit 생성자를 만들고 위와 같은 결과를 출력하는 객체를 만들어보자
// Fruit(name, emoji)
// const apple = new Fruit('apple', '🍎');
// console.log(apple);
// apple.display();

function Fruit(name, emoji){
    this.name = name
    this.emoji = emoji
    this.display = function(){
        console.log(`${this.name} : ${emoji}`)
    }

}

const melon = new Fruit('김메론', '🍈')
console.log(melon) // Fruit { name: '김메론', emoji: '🍈', display: [Function (anonymous)] }
melon.display(); // 김메론 : 🍈

const charry = new Fruit('김채리', '🍒')
console.log(charry)
charry.display();

Class

더보기
class Fruit {

    // static
    // 정적 프러퍼티 및 메서드를 생성
    // 클래스 레벨 메서드에서는 this를 참조할 수 없음
    static count_fruits = 10; // 메모리에 올라가 있기 때문에 객체를 생성하지 않아도 됨

    static makeBanana(){
        return new Fruit('banana', '🍌');
    }
    constructor(name, emoji){
        this.name = name;
        this.emoji = emoji;
    
    }
    display = () => {
        console.log(`${this.name} : ${this.emoji}`)
    }
}

const apple = new Fruit('apple', '🍎')
console.log(apple);
apple.display();

console.log('----------------------');

console.log(Fruit.count_fruits); //10 
const banana = Fruit.makeBanana();
console.log(banana);


// 객체지향 프로그래밍의 은닉성
// private :  외부에서 접근할 수 없는 변수

class Dog{
    #name; // private
    #color;
    constructor(name, color){
        this.#name = name
        this.#color = color
    }
    // 프러퍼티명과 setter 프러퍼티 메서드의 이름은 일치할 필요 없음
    set name(value){
        console.log('set', value);
        this.#name = value;
    }

    get name(){
        return this.#name;
    }
    set color(value){
        console.log('set', value);
        this.#color = value;
    }

    get color(){
        return this.#color;
    }

    run = () => {
        console.log(`${this.#color} 색상의 강아지 ${this.#name} 달립니다.`);
    }

    #eat = () => {
        console.log(`${this.#name} 사료를 먹습니다`)
    }

    myEat = () => {
        this.#eat();
    }

}
const Rucy = new Dog('루시', '흰색');
console.log(Rucy);
console.log(Rucy.name);

// set 프러퍼티가 실행 
Rucy.name = '뽀미';
// get 프러퍼티가 실행
console.log(Rucy.name);

Rucy.run();// Rucy.eat();     private라서  error
Rucy.myEat();

/*

문제

 카운터 만들기
 카운터를 0으로 값을 초기화 한 뒤 하나씩 값이 증가하는 메서드를 구현한 클래스를 만들어보자.
 단, 객체 생성시 값이 0보다 작을 경우 0으로 초기화를 시키고 그 외의 값은 입력한 값으로 설정.
 또한 프러퍼티에 값을 직접 불러오거나 설정할 수 없음
    const cnt = new Counter(0); //10
    cnt.increment(); /11
    cnt.increment(); /12
 */


    console.log('----------------------');


class Counter{
    #value;
    constructor(value){
        if(isNaN(value) || value < 0){
            this.#value = 0;
        }
        else{
        this.#value = value;
    }
    }
   
    get value(){
        return this.#value;
    }
    
    increment = () => {
        this.#value++;

}
}
const cnt = new Counter(-1);
console.log(cnt.value);
cnt.increment();
cnt.increment();
cnt.increment();
console.log(cnt.value);

inherit

더보기
class Fruit {

    // static
    // 정적 프러퍼티 및 메서드를 생성
    // 클래스 레벨 메서드에서는 this를 참조할 수 없음
    static count_fruits = 10; // 메모리에 올라가 있기 때문에 객체를 생성하지 않아도 됨

    static makeBanana(){
        return new Fruit('banana', '🍌');
    }
    constructor(name, emoji){
        this.name = name;
        this.emoji = emoji;
    
    }
    display = () => {
        console.log(`${this.name} : ${this.emoji}`)
    }
}

const apple = new Fruit('apple', '🍎')
console.log(apple);
apple.display();

console.log('----------------------');

console.log(Fruit.count_fruits); //10 
const banana = Fruit.makeBanana();
console.log(banana);


// 객체지향 프로그래밍의 은닉성
// private :  외부에서 접근할 수 없는 변수

class Dog{
    #name; // private
    #color;
    constructor(name, color){
        this.#name = name
        this.#color = color
    }
    // 프러퍼티명과 setter 프러퍼티 메서드의 이름은 일치할 필요 없음
    set name(value){
        console.log('set', value);
        this.#name = value;
    }

    get name(){
        return this.#name;
    }
    set color(value){
        console.log('set', value);
        this.#color = value;
    }

    get color(){
        return this.#color;
    }

    run = () => {
        console.log(`${this.#color} 색상의 강아지 ${this.#name} 달립니다.`);
    }

    #eat = () => {
        console.log(`${this.#name} 사료를 먹습니다`)
    }

    myEat = () => {
        this.#eat();
    }

}
const Rucy = new Dog('루시', '흰색');
console.log(Rucy);
console.log(Rucy.name);

// set 프러퍼티가 실행 
Rucy.name = '뽀미';
// get 프러퍼티가 실행
console.log(Rucy.name);

Rucy.run();// Rucy.eat();     private라서  error
Rucy.myEat();

/*

문제

 카운터 만들기
 카운터를 0으로 값을 초기화 한 뒤 하나씩 값이 증가하는 메서드를 구현한 클래스를 만들어보자.
 단, 객체 생성시 값이 0보다 작을 경우 0으로 초기화를 시키고 그 외의 값은 입력한 값으로 설정.
 또한 프러퍼티에 값을 직접 불러오거나 설정할 수 없음
    const cnt = new Counter(0); //10
    cnt.increment(); /11
    cnt.increment(); /12
 */


    console.log('----------------------');


class Counter{
    #value;
    constructor(value){
        if(isNaN(value) || value < 0){
            this.#value = 0;
        }
        else{
        this.#value = value;
    }
    }
   
    get value(){
        return this.#value;
    }
    
    increment = () => {
        this.#value++;

}
}
const cnt = new Counter(-1);
console.log(cnt.value);
cnt.increment();
cnt.increment();
cnt.increment();
console.log(cnt.value);

 

iterator

더보기
이터레이터(Iterator)
- next() 메서드를 구현하는 객체
- next() 메서드는 현재 요소를 반환하고 다음 요소로 이동
- 이터레이터는 이터러블 객쳉의 요소를 반복하는데 사용

const arr = [1, 2, 3, 4, 5];
console.log(arr.values());
console.log(arr.entries());
console.log(arr.keys());

const iterator = arr.values();

while(true){
    const item = iterator.next();
    if(item.done) break;
     console.log(item.value);
    }                               // 12345

for(let item of arr){
    console.log(item);
}                                   // 12345

 

iterable

더보기
이터러블(Iterable)
- 이터러블은 [Symbol.lterator] 메서드를 구현하는 객체
- [Symbol.Iterator] 메서드는 이터레이터를 반환하는 메서드
- 이터러블 객체는 for..of 루프나 배열 같은 반복 가능한 객체를 사용하는 문맥에서 반복될 수 있음

function iterable(){
    let index =  0;
    let data=[1,2,3,4];

    return{
        next(){
            if(index< data.length){
                return {value:data[index++], done:false};
            }
            else{return {value:undefined, done:true}}
        }
    }

}
let i = iterable();
console.log(i.next());
console.log(i.next());
console.log(i.next());
console.log(i.next());
console.log(i.next());

 

spread

더보기
// 원시값과 객체값의 비교
// 원시값 : 값에 의한 복사가 일어남
// 객체값 : 참조에 의한 복사 (메모리 주소)

function display(num){
    num = 10;
    console.log(num);
    
}
const value = 5;
display(value); // 10
console.log(value); // 5

// 객체의 값을 변경하는 것은 좋지 않은 알고리즘이다.
function displayObj(obj){
    obj.age = 14;
    console.log(obj);
}

const Rucy = {name:"루시", age:10}
displayObj(Rucy); // { name: '루시', age: 14 }
console.log(Rucy); // { name: '루시', age: 14 }
console.log(Rucy.age); // 14

// 객체를 복사하여 age를 변환하고 해당 객체를 반환시켜준다.
function changeAge(obj){
    return {...obj, age: 6};

}
PPomi = changeAge(Rucy);
console.log(Rucy); // { name: '루시', age: 14 }
console.log(PPomi); // { name: '루시', age: 6 }

function add(num1, num2, num3){
    return num1 + num2 + num3;
}
console.log(add(10, 20, 30)); // 60

const nums = [10, 20, 30];
console.log(add(nums[0],nums[1],nums[2])); // 60

console.log(add(...nums)); // 60


const fruits1  = ['🍌','🍎'];
const fruits2  = ['🍎','🍒'];

let arr = fruits1.concat(fruits2);
console.log(arr) // [ '🍌', '🍎', '🍎', '🍒' ]
arr = [...fruits1, ...fruits2]
console.log(arr) // [ '🍌', '🍎', '🍎', '🍒' ]
arr = [...fruits1, '🍈',...fruits2]
console.log(arr) // [ '🍌', '🍎', '🍈', '🍎', '🍒' ]




const apple = {name : '김사과', age : 20, address : {si : '서울시', gu:'서초구', dong:'양재동'}};
console.log(apple);

const new_apple = {...apple, job:'프로그래머'}; 

console.log(apple); // { name: '김사과', age: 20, adress: { si: '서울시', gu: '서초구', dong: '양재동' } }
console.log(new_apple);
// { name: '김사과', age: 20, adress: { si: '서울시', gu: '서초구', dong: '양재동' }, job: '프로그래머'}


const fruits = ['🍈', '🍒', '🍎', '🍌'];
const [fruit1, fruit2, ... others] = fruits;
console.log(fruit1); // 🍈
console.log(fruit2); // 🍒
console.log(others); // [ '🍎', '🍌' ]


function sendEmoji(){
    return ['🍈', '🍒', '🍎', '🍌'];
}
const [f1, f2, f3, f4] = sendEmoji();
console.log(f1);
console.log(f2);
console.log(f3);
console.log(f4);

console.log(new_apple);
function display({name, age, address, job}){
    console.log('이름', name);
    console.log('나이', age);
    console.log('주소', address);
    console.log('직업', job);
}


display(new_apple); //이름 김사과 나이 20 주소 { si: '서울시', gu: '서초구', dong: '양재동' } 직업 프로그래머

const {name, age, pet ='루시', address, job : hobby} = new_apple;
console.log(name); // 김사과
console.log(age); // 20
console.log(pet); // 루시
console.log(address); // { si: '서울시', gu: '서초구', dong: '양재동' }
console.log(hobby); // 프로그래머


const component = {
    name : 'Button',
    styles:{
        size : 20,
        color : 'black'
    }

};
function changeColor({styles: {color}}){
    console.log(color);
}
changeColor(component); // black