자바스크립트 (함수)

이종경·2024년 4월 12일
0

자바스크립트

목록 보기
3/11
post-thumbnail

함수는 생각보다 복잡하다.

1. 함수는 일급객체이다.

자바스크립트에서 함수는 일급객체이므로 아래와 같은 특징이 있다

  • 무명(Anonymous)의 리터럴로 표현이 가능하다.
  • 변수나 자료구조(객체, 배열)에 저장할 수 있다.
  • 함수의 파라미터로 전달할 수 있다.
  • 반환값(return value)으로 사용할 수 있다.

일급 : 사용할 때 다른 요소들과 아무런 차별이 없다는 것을 뜻한다.

// 기명 함수 표현식(named function expression)
var foo = function multiply(a, b) {
  return a * b;
};

// 익명 함수 표현식(anonymous function expression)
var bar = function(a, b) {
  return a * b;
};

console.log(foo(10, 5)); // 50
console.log(multiply(10, 5)); // Uncaught ReferenceError: multiply is not defined
// 함수 표현식에서 사용한 함수명은 외부 코드에서 접근 불가능하기 때문에 에러 발생

함수는 일급객체이기 때문에 변수에 할당할 수 있는데 이 변수는 함수명이 아니라 할당된 함수를 가리키는 참조값을 저장하게 된다. 함수 호출시 함수명이 아니라 함수를 가리키는 변수명을 사용하여야 한다.

function square (number) { // 함수 선언문
  return number * number;
}

/* 함수 선언문으로 정의한 함수의 경우, 함수명으로 호출이 가능했던 이유는
자바스크립트 엔진에 의해 아래와 같은 함수 표현식으로 형태가 변경되었기 때문이다.
*/
var square = function square(number) {
  return number * number;
}

함수명과 함수 참조값을 가진 변수명이 일치하므로 함수명으로 호출되는 듯 보이지만 사실은 변수명으로 호출된 것이다.

결국 함수 선언문도 함수 표현식과 동일하게 함수 리터럴 방식으로 정의되는 것이다.
이것은 결국 내장 함수 Function 생성자 함수로 함수를 생성하는 것을 단순화시킨 short-hand(축약법)이다.

즉, 함수를 정의하는 방식은 달라도 결국 Function 생성자 함수로 함수를 생성하는 것이다.

2. 함수의 호이스팅

함수의 호이스팅은 두가지 방식으로 나뉜다.

함수 선언문으로 함수를 선언하는 경우

함수 선언문으로 정의된 함수는 자바스크립트 엔진이 스크립트가 로딩되는 시점에 바로 초기화하고 이를 VO(variable object)에 저장한다. 즉, 함수 선언, 초기화, 할당이 한번에 이루어진다. 그렇기 때문에 함수 선언의 위치와는 상관없이 소스 내 어느 곳에서든지 호출이 가능하다

var res = square(5); // undefined

function square(number) {
  return number * number;
}

함수 표현식으로 함수를 선언하는 경우

함수 표현식의 경우 함수 호이스팅이 아니라 변수 호이스팅이 발생한다.

변수 호이스팅은 변수 생성 및 초기화와 할당이 분리되어 진행된다. 호이스팅된 변수는 undefined로 초기화 되고 실제값의 할당은 할당문에서 이루어진다.

var res = square(5); // TypeError: square is not a function

var square = function(number) {
  return number * number;
}

3. 함수에서 객체형 인수의 동작

객체형(참조형) 인수는 Call-by-reference(참조에 의한 호출)로 동작한다.
함수 호출 시 참조 타입 인수를 함수에 매개변수로 전달할 객체의 참조값이 매개변수에 저장되어 함수로 전달된다. 따라서 함수 내에서 참조값을 이용해 값을 변경하면 참조형의 인수값도 변경된다.

function changeVal(primitive, obj) {
  primitive += 100;
  obj.name = 'Kim';
  obj.gender = 'female';
}

var num = 100;
var obj = {
  name: 'Lee',
  gender: 'male'
};

console.log(num); // 100
console.log(obj); // Object {name: 'Lee', gender: 'male'}

changeVal(num, obj);

console.log(num); // 100
console.log(obj); // Object {name: 'Kim', gender: 'female'}

참조

4. 함수 객체의 프로퍼티

함수는 객체이므로 프로퍼티를 가질 수 있다.
함수가 갖는 프로퍼티로는 arguments, caller, length, name가 있다.

유사 배열 arguments

arguments 객체는 함수 호출 시 전달된 인수(argument)들의 정보를 담고 있는 순회가능한(iterable) 유사 배열 객체(array-like object)이며 함수 내부에서 지역변수처럼 사용된다.

유사배열객체란 length 프로퍼티를 가진 객체를 말한다.
배열이 아니므로 배열 메소드를 사용하는 경우 에러가 발생하게 된다.

function multiply(x, y) {
  console.log(arguments);
  return x * y;
}

multiply();        // {}
multiply(1);       // { '0': 1 }
multiply(1, 2);    // { '0': 1, '1': 2 }
multiply(1, 2, 3); // { '0': 1, '1': 2, '2': 3 }

날 호출한 함수, caller

caller는 자신을 호출한 함수를 의미한다.

function foo(func) {
  var res = func();
  return res;
}

function bar() {
  return 'caller : ' + bar.caller;
}

console.log(foo(bar)); // caller : function foo(func) {...}
console.log(bar());    // null (browser에서의 실행 결과)

매개변수의 길이 length

length 프로퍼티는 함수 정의 시 작성된 매개변수 갯수를 의미한다.

function bar(x) {
  console.log(arguments.length)
  return x;
}
console.log(bar.length) // 1
console.log(bar(3,4,5)) // arguments.length: 3

4. prototype

프로토타입 객체란 프로토타입 기반 객체 지향 프로그래밍의 근간을 이루는 객체로서 객체간의 상속(Inheritance)을 구현하기 위해 사용된다
즉, 다른 객체에 공유 프로퍼티를 제공하는 객체를 말한다.
prototype 프로퍼티는 함수가 객체를 생성하는 생성자 함수로 사용될 때, 생성자 함수가 생성한 인스턴스의 프로토타입 객체를 가리킨다.

proto를 통한 prototype 객체로 접근

proto 프로퍼티는 모든 객체의 프로토타입 객체인 Object.prototype 객체의 프로퍼티이다. 모든 객체는 상속을 통해 __proto__ 접근자 프로퍼티는 사용할 수 있다.

// 객체는 __proto__ 프로퍼티를 소유하지 않는다.
console.log(Object.getOwnPropertyDescriptor({}, '__proto__'));
// undefined

// __proto__ 프로퍼티는 모든 객체의 프로토타입 객체인 Object.prototype의 접근자 프로퍼티이다.
console.log(Object.getOwnPropertyDescriptor(Object.prototype, '__proto__'));
// {get: ƒ, set: ƒ, enumerable: false, configurable: true}

// 모든 객체는 Object.prototype의 접근자 프로퍼티 __proto__를 상속받아 사용할 수 있다.
console.log({}.__proto__ === Object.prototype); // true

5. 즉시 실행 함수

즉시 실행 함수(IIFE, Immediately Invoke Function Expression)란 함수의 정의와 동시에 실행되는 함수를 말한다. 최초 한번만 호출되며 다시 호출할 수는 없다.

// 기명 즉시 실행 함수(named immediately-invoked function expression)
(function myFunction() {
  var a = 3;
  var b = 5;
  return a * b;
}());

// 익명 즉시 실행 함수(immediately-invoked function expression)
(function () {
  var a = 3;
  var b = 5;
  return a * b;
}());

함수편을 마무리하며

당장 사용하는 데 있어서 문제 되는 게 없어 깊이 알 필요 없다고 생각했었다. 하지만 그건 내가 너무 거만해져 있던 건 아닌가 싶다.

참고
자바스크립트의 기본

profile
작은 성취들이 모여 큰 결과를 만든다고 믿으며, 꾸준함을 바탕으로 개발 역량을 키워가고 있습니다

0개의 댓글