Lsiron

Java Script -함수 (feat. Elice) 본문

언어/Java Script

Java Script -함수 (feat. Elice)

Lsiron 2024. 5. 3. 13:41

★ parameter, argument

인자(argument)는 어떤 함수가 호출될 때 전달되는 을 의미하고

매개변수(parameter)는 전달된 값을 받아들이는 변수를 의미한다.

function sum(a, b) { // a,b 는 매개변수(parameter)
  return a + b;
}
sum( 10, 20 ) // 10, 20은 인자(argument)
 

★참조형에 따른 방식

일반적으로 기본형(원시형)을 매개변수로 넘길 때는 Call by value 방식으로 넘기고

참조형을 매개변수로 넘길 때는 Call by reference 방식으로 넘긴다.

기본형(원시형) : 숫자, 문자열, 불리언, null, undefiend, 심볼

참조형 : 객체, 배열, 함수, 날짜, 정규표현식

call by value 콜바이벨류(Call by Value)는 함수가 인수로 전달받은 값을 복사하여 처리하는 방식이다.
이때, 전달된 값은 기본형, 즉 JS의 원시 타입(primitive type) 데이터인 경우에 해당하며, 변수가 가진 값을 복사하여 전달하므로 함수 내에서 값을 변경해도 원본 값은 변경되지 않는다. 따라서 값의 불변성(Immutability)을 유지하는 데에 용이하다.

function addOne(x) {
  x += 1;
  return x;
}

let num = 5;
console.log(addOne(num)); // 6
console.log(num); // 5

위 예시에서 num 변수가 가진 값을 addOne() 함수에 인수로 전달하면, x라는 새로운 변수에 값이 복사된다.
addOne() 함수 내에서 x 값을 변경해도 원본 num 값은 변경되지 않는다.

  • 장점 : 복사하여 처리하기 때문에 안전하다. 원래의 값이 보존이 된다.
  • 단점 : 복사를 하기 때문에 메모리가 사용량이 늘어난다.

 

call by reference 콜바이레퍼런스(Call by Reference)란 함수 호출 시 인수로 전달되는 변수의 참조 값을 함수 내부로 전달하는 방식이다.
이 방식에서는 함수 내에서 인자로 전달된 변수의 값을 변경하면, 호출한 쪽에서도 해당 변수의 값이 변경된다. 이는 인자로 전달되는 값이 변수의 주소이므로, 함수 내에서 변수의 값을 변경하면 해당 주소에 저장된 값이 변경되기 때문이다.

function addOne(arr) {
  arr.push(1);
  return arr;
}

let nums = [1, 2, 3];
let result = addOne(nums);
console.log(result); // 출력: [1, 2, 3, 1]
console.log(nums); // 출력: [1, 2, 3, 1] (원본 값도 함께 변경됨)

예시에서 addOne 함수에 nums 변수의 참조 값을 전달하면, arr 변수에도 nums 변수의 참조 값이 복사된다.
따라서, 함수 내부에서 arr 값을 변경하면 원본 nums 값도 함께 변경된다.

  • 장점 : 복사하지 않고 직접 참조를 하기에 빠르다.
  • 단점 : 직접 참조를 하기에 원래 값이 영향을 받는다.(리스크)

★콜 바이 레퍼런스 단점의 보완

원래 값이 영향을 받는 단점을 보완하려면 어떻게 해야할까?

콜 바이 레퍼런스는 참조 타입을 전달하는 방식이다. 참조 타입의 경우 객체의 참조 값이 복사되므로, 객체 내부의 값이 변경되면 원본 객체도 함께 변경되는 문제가 발생한다. 그렇다면 우리는 원본의 불변성은 지킬 수 없게된다. 데이터의 원본이 수정되는 불상사가 발행하는 것이다.

 

이러한 문제점을 해결하려면 어떻게 해야할까?

얕은복사 깊은복사에서 깊은복사(deep copy)를 이용하는 방법이 있다.

깊은복사(deep copy)도 마찬가지로 객체를 복사하였을 때 원본에 영향을 주지않는 방식을 사용하고 있다.

 

물론 단점의 보완을 위해 복사를 사용하게 되면 메모리를 소모하게 되고, 속도의 장점을 잃어버릴 수 있다.
따라서 깊은 복사와 콜바이레퍼런스를 함께 사용할 때는 상황에 따라서 적절히 선택해야 할 것이다.

원본변경을 해야하는 인수라면 그대로 동작시키고, 불변성을 지켜야 한다면 깊은복사를 이용해서 동작시킬 필요성이 생길 것이다.

아래는 함수 호출 시 인수로 전달되는 변수의 참조 값을 함수 내부로 전달하되 참조 객체를 깊은복사를 통해 전달하여, 원본의 불변성을 지키는 예시이다.


function changeName(obj) {
  obj = JSON.parse(JSON.stringify(obj)); // 깊은 복사
  obj.name = 'John';
  return obj;
}

let person = { name: 'Jane', age : 25};
let result = changeName(person);
console.log(result); // 출력: { name: 'John', age: 25}
console.log(person); // 출력: { name: 'Jane', age: 25} (원본 값은 변경되지 않음)

★생성자 함수 예제

//문제 5번

문제 5. 클래스를 완성해주세요.
class Vehicle {}
조건 1. 자동차(cars)의 개수를 초기화 할 수 있어야 합니다.
조건 2. Vehicle 클래스의 인스턴스를 만들어서 변수 vehicle에 할당해 주세요.

//문제 5번 답
class Vehicle {
    cars = 0;
 
  constructor(cars) {
  this.cars= cars;
      }
  }
  const vehicle = new Vehicle (100);
 
//문제 6번
문제 6. 주어진 코드를 이용해 Korea  클래스의 name을 "대한민국"으로 초기화하는 부분을 작성하세요.
class Korea {
    name = "";
  }
  class Elice extends Korea {
      students = 0;
 
      constructor(students) {
          this.students = students;
      }
  }

// 문제 6번 답
class Korea {
    name = "";
    constructor(name) {
      this.name = name;
    }
  }
  class ELice extends Korea {
    students = 0;
    constructor(students)  {
    super("대한민국");
    this.students = students;
    }
  }
// 문제 7번

문제 7. 주어진 코드를 이용해 Elice 클래스의 인스턴스를 만들고, 인스턴스를 활용해 Elice의 sayName을 실행해보세요.

class Korea {
  name = "";

  constructor(name) {
    this.name = name;
  }
}
class Elice extends Korea {
  students = 0;

  constructor(students) {
    super("대한민국");
    this.students = students;
  }
}

// 문제 7번 답

class Korea {
  name = "";

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

  sayName() {
    console.log("코리아");
  }
}
class Elice extends Korea {
  name = "";

  constructor(name) {
    super(name);
    this.name = name;
  }

  sayName() {
    console.log("엘리스");
  }
}

const elice = new Elice("엘리스"); // 인스턴스 생성
elice.sayName(); // 엘리스



// 문제 7-1번

문제 7-1. Elice의 인스턴스를 사용해 sayName을 호출한 결과가 "코리아"가 되도록 코드를 수정해보세요.

class Korea {
  name = "";

  constructor(name) {}

  sayName() {
    console.log("코리아");
  }
}
class Elice extends Korea {
  name = "";

  constructor(name) {}

  sayName() {
    console.log("엘리스");
  }
}



// 문제 7-1번 답
class Korea {
  name = "";

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

  sayName() {
    console.log("코리아");
  }
}
class Elice extends Korea {
  name = "";

  constructor(name) {
    super(name);
    this.name = name;
  }

  sayName() {
    // super 키워드로 상속받는 클래스를 가리키게 됩니다.
    super.sayName();
  }
}

const elice = new Elice("엘리스"); // 인스턴스 생성
elice.sayName(); // 코리아

'언어 > Java Script' 카테고리의 다른 글

Java Script -This, 실행컨텍스트, prototype, closure (feat. Elice)  (0) 2024.05.09
Java Script -DOM 객체 (feat. Elice)  (0) 2024.05.08
4.조건문과 반복문  (0) 2024.04.22
3.연산자  (0) 2024.04.21
2.Hoisting  (0) 2024.04.21