본문 바로가기
프론트엔드/자바스크립트

함수1

by iks15174 2021. 6. 16.

함수는 입력(input)을 받은 다음 함수 내부의 로직에 따라 입력을 처리하고 출력(output)을 하는 일련의 과정을 정의한 것이다. 자바스크립트에서 함수는 하나의 객체이다.

function add1(a, b){
    return a + b;
}

let add2 = function(a, b){
    return a + b;
}

console.log(add1(2, 5)); // 7

console.log(add2(5, 10)); // 15

위의 예시는 자바스크립트에서 add1과 add2라는 함수를 정의한 것이다. add1과 add2라는 함수는 a, b라는 입력을 받고 내부에서 a + b라는 로직을 수행한 후 그 값을 출력하고 있다. add1(2, 5)를 보면 2, 5라는 값이 a, b라는 변수를 통해 함수 외부에서 내부로 전달된다.

add1, add2를 함수 이름 / a, b를 매개변수 / (2, 5) or (5, 10)을 인수 / return a + b; 를 반환 값이라고 한다.

 

자바스크립트에서 함수는 일급 객체이기 때문에 두번째 예시처럼 함수를 선언하고 add2라는 변수에 할당할 수 있다. 

즉 add2는 함수 객체를 담고 있는 변수이다.

그렇다면 add1이라는 변수는 어디서 나온 것 일까? 자바스크립트 엔진은 첫 번째 예시처럼 함수를 정의할 경우 함수 이름과 동일한 이름의 변수를 암묵적으로 생성하고, 거기에 함수 객체를 할당한다. 즉 add1이라는 변수를 암묵적으로 생성해 우리가 정의한 함수 객체를 할당한 것이다. 그러므로 add1(2, 5) 같이 호출할 수 있는 것이다.

 

이번에는 자바스크립트의 함수 정의 방법에 대해 알아보겠다.

1. 함수 선언문

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

2. 함수 표현식

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

3. Function 생성자 함수

let add = new Function('x', 'y', 'return x + y');

4. 화살표 함수(ES6)

let add = (x, y) => x + y;

4가지의 함수 선언 방식이 있다. 화살표 함수의 경우 this 바인딩이 다르다. 이 내용은 이후에 알아보겠다.

 

함수가 생성되면 메모리에 어떤 모습으로 담기는지 알아보겠다.

 

 

add라는 변수 안에는 함수 객체가 담겨있지 않다. 함수 객체를 참조하는 주소가 담겨 있다. 즉 add라는 변수는 현재 0x000000F2를 주소를 가진 곳에 위치한다. 그리고 add는 0x00001122라는 값을 가지고 있다. 이 값은 함수 객체가 담겨 있는 주소를 의미한다. 함수 객체뿐만이 아니라 자바스크립트의 모든 객체가 위와 같은 형식으로 저장된다.

 

자바스크립트는 원시값 이거나 객체로 이루어져 있다. 그렇다면 원시 값은 어떤 형식으로 저장될까?

let a = 2;

일단 let a를 하면 a라는 변수를 위한 공간이 메모리에 생긴다. 위 그림에서 a라는 변수 공간의 주소는 0x000000F2이다. 그리고 let a = 2 이기 때문에 a라는 변수를 위한 공간에 2가 그대로 할당된다. 이것이 자바스크립트에서 객체와 원시 값이 메모리에 등록될 때의 차이점이다. 객체가 할당된 변수는 객체 그 자체를 담고 있는 것이 아니라 객체를 참조하는 주소를 담고 있지만 원시 값이 할당된 변수는 값 그 자체를 담고 있다.

 

이번에는 원시값과 객체의 값 할당에 대해 좀 더 자세히 알아보겠다.

let a = 10;
let copy = a;

console.log(a === copy); //true

a = 20;

console.log(a === copy); // false

위의 그림은 10이라는 정수(원시 값)를 담고 있는 a 변수를 선언하고 copy 변수에 a를 할당하고 있다. 그다음 a와 copy에 들어 있는 값을 비교했을 때는 같다. 하지만 a 변수의 값을 20으로 바꾸고 다시 비교했을 때 a와 copy는 같지 않다. a는 20으로 바뀌었지만 copy는 그대로 10이기 때문이다. 어떤 일이 일어났는지 자세히 알아보겠다. 먼저 let a = 10; 코드를 실행하면 메모리에 a 변수를 위한 공간이 만들어지고 그 공간에 10이 할당된다. 그 다음 let copy = a; 코드를 실행하면 메모리에 copy 변수를 위한 공간이(a와는 다른 공간임) 만들어 진다. 그리고 그 공간에 a변수에 들어 있는 값인 10이 할당된다. 즉 a와 copy는 서로 다른 공간을 가지고 있다는 의미다. 그렇기 때문에 a = 20; 코드를 실행했을 떄 a변수의 값만 바뀌는 것이다. 아래 그림은 a와 copy 변수가 메모리에 어떻게 올라가 있는지 대략적으로 나타낸 것이다.

 

 

 

이번에는 객체의 값 할당에 대해 알아보겠다. 원시 값을 가지는 변수와 크게 차이는 없다. 다만 객체를 담고 있는 변수는 변수 안에 객체 그 자체가 담겨 있는 게 아니라 객체를 참조하는 주소를 가지고 있기 때문에 동작이 조금 달라진다.

let person = {
    name : "JIHO",
    age : 20,
    toString(){
        return (`name : ${this.name}, age : ${this.age}`);
    }
}

let personCopy = person;
console.log(person.toString()); //name : JIHO, age : 20
console.log(personCopy.toString()); //name : JIHO, age : 20

person.age = 24;
person.name = 'PARK';

console.log(person.toString()); //name : PARK, age : 24
console.log(personCopy.toString()); //name : PARK, age : 24

 

위의 그림에서 person이라는 객체를 생성하였다. 객체 리터럴 방식을 이용해 생성하였으며 프로퍼티로는 name과 age를 가지고 메서드는 toString을 가진다. 그 후 personCopy라는 변수에 person 객체를 할당해 주었다. 위의 그림을 실행했을 때 메모리에서 어떤 일이 일어나는지 자세히 알아보도록 하겠다. 먼저 메모리상에 객체가 생성된다. 그리고 person 변수를 위한 메모리 공간도 생성되며 person 변수 메모리 공간에는 객체의 주소가 담기게 된다(객체가 담기는 것이 아니라 객체가 있는 메모리 공간의 주소가 담기는 것에 주의하자). 그 후 personCopy 변수를 위한 메모리 공간이 생성되고 personCopy 메모리 공간에 person의 값을 할당한다. 즉 객체의 주소를 할당한다는 것이다. 그러므로 person과 personCopy 변수에는 객체를 가리키는 주소가 존재하게 된다. 그 후 person.age = 24; person.name = 'PARK'; 를 통해 객체의 프로퍼티를 변경해 준다. personCopy 변수도 같은 객체를 가리키고 있기 때문에 personCopy.age와 personCopy.name 도 변경이 된다. 아래 그림은 위의 과정을 대략적으로 나타낸 것이다.

 

'프론트엔드 > 자바스크립트' 카테고리의 다른 글

함수의 scope  (0) 2021.06.21
함수2  (0) 2021.06.17
자바스크립트 객체  (0) 2021.06.14