본문으둜 κ±΄λ„ˆλ›°κΈ°

4. ν•¨μˆ˜μ™€ ν”„λ‘œν† νƒ€μž… 체이닝 - 1

이 글은 κ³ ν˜„μ€€, μ†‘ν˜•μ£Ό λ‹˜μ˜ μΈμ‚¬μ΄λ“œ μžλ°”μŠ€ν¬λ¦½νŠΈλ₯Όμ°Έμ‘°ν•˜μ—¬ μž‘μ„±ν•œ κΈ€μž…λ‹ˆλ‹€.

JavaScript의 κ°€μž₯ μ€‘μš”ν•œ κ°œλ… 1μˆœμœ„λŠ” λ‹Ήμ—°νžˆ ν•¨μˆ˜λ‹€. JS의 ν•¨μˆ˜λŠ” λͺ¨λ“ˆν™” μ²˜λ¦¬λ‚˜ ν΄λ‘œμ €, 객체 생성 λ“± μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ 근간이 λ˜λŠ” λ§Žμ€ κΈ°λŠ₯을 μ œκ³΅ν•˜κ³  μžˆλ‹€.

ν•¨μˆ˜ μ •μ˜#

JSμ—μ„œ ν•¨μˆ˜λ₯Ό μƒμ„±ν•˜λŠ” 방법은 4가지이닀.

  • ν•¨μˆ˜ μ„ μ–Έλ¬Έ(function statement)

  • ν•¨μˆ˜ ν‘œν˜„μ‹(function expression)

  • Function() μƒμ„±μž ν•¨μˆ˜

    • (ES6) ν™”μ‚΄ν‘œ ν•¨μˆ˜(arrow function)

ν•¨μˆ˜ λ¦¬ν„°λŸ΄#

λ¦¬ν„°λŸ΄ : ν•¨μˆ˜λ₯Ό μƒμ„±ν•˜λŠ” ν‘œκΈ°λ²•μœΌλ‘œ μƒκ°ν•˜λ©΄ λœλ‹€. ex) 객체 λ¦¬ν„°λŸ΄, λ°°μ—΄ λ¦¬ν„°λŸ΄ ...

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

ν•¨μˆ˜ λ¦¬ν„°λŸ΄μ€ 크게 λ„€ λΆ€λΆ„μœΌλ‘œ κ΅¬μ„±λœλ‹€.

  • function ν‚€μ›Œλ“œ : ν•¨μˆ˜ λ¦¬ν„°λŸ΄μ€ function ν‚€μ›Œλ“œλ‘œ μ‹œμž‘.

  • ν•¨μˆ˜λͺ… [μ˜΅μ…”λ„] : ν•¨μˆ˜ λ‚΄λΆ€ μ½”λ“œμ—μ„œ μž¬κ·€μ  호좜 λ˜λŠ” 디버거가 κ΅¬λΆ„ν•˜κΈ° μœ„ν•œμ‹λ³„μžλ‘œ μ‚¬μš©.

  • λ§€κ°œλ³€μˆ˜ 리슀트 : λ‹€λ₯Έ 언어와 달리 λ§€κ°œλ³€μˆ˜ νƒ€μž…μ„ κΈ°μž…ν•˜μ§€ μ•ŠλŠ”λ‹€.

  • ν•¨μˆ˜ λͺΈμ²΄ : ν•¨μˆ˜κ°€ ν˜ΈμΆœλμ„ λ•Œ μ‹€ν–‰λ˜λŠ” λΆ€λΆ„.


ν•¨μˆ˜ μ„ μ–Έλ¬Έ#

ν•¨μˆ˜ 선언문은 ν•¨μˆ˜ λ¦¬ν„°λŸ΄ ν˜•νƒœλ₯Ό κ·ΈλŒ€λ‘œ μ΄μš©ν•˜λŠ”λ°, ν•¨μˆ˜ μ„ μ–Έμ˜ 경우 λ°˜λ“œμ‹œ ν•¨μˆ˜λͺ…이 μžˆμ–΄μ•Ό ν•œλ‹€.

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

☝ ν•¨μˆ˜ 선언은 hoisting 이 λ°œμƒν•˜λ―€λ‘œ μ‚¬μš©μ— 주의. (ν•¨μˆ˜ ν‘œν˜„μ‹ μ‚¬μš©μ„ ꢌμž₯)


ν•¨μˆ˜ ν‘œν˜„μ‹#

ν•¨μˆ˜ λ¦¬ν„°λŸ΄λ‘œ ν•˜λ‚˜μ˜ ν•¨μˆ˜λ₯Ό λ§Œλ“€κ³  λ³€μˆ˜μ— ν• λ‹Ήν•˜μ—¬ ν•¨μˆ˜λ₯Ό μƒμ„±ν•˜λŠ” 것을 ν•¨μˆ˜ ν‘œν˜„μ‹μ΄λΌκ³  ν•œλ‹€.

이 경우 ν•¨μˆ˜λͺ…이 선택 사항이며 보톡 μ‚¬μš©ν•˜μ§€ μ•ŠλŠ”λ‹€. μ΄λŸ¬ν•œ ν•¨μˆ˜λ₯Ό 읡λͺ… ν•¨μˆ˜λΌ ν•œλ‹€.

var add = function (x, y) {    return x + y;};
var plus = add;
console.log(add(3, 4)); // 7console.log(plus(5, 6)); // 11
  • μ—¬κΈ°μ„œ add λ³€μˆ˜λŠ” ν•¨μˆ˜ λ¦¬ν„°λŸ΄λ‘œ μƒμ„±ν•œ ν•¨μˆ˜λ₯Ό μ°Έμ‘°ν•˜λŠ” λ³€μˆ˜μ΄μ§€ ν•¨μˆ˜λͺ…이 μ•„λ‹ˆλ‹€. μ΄λŸ¬ν•œ λ³€μˆ˜λ₯Ό ν•¨μˆ˜ λ³€μˆ˜λΌκ³  λΆ€λ₯Έλ‹€.

  • ν•¨μˆ˜ λ³€μˆ˜ add λŠ” ν•¨μˆ˜μ˜ 참쑰값을 κ°€μ§€λ―€λ‘œ λ‹€λ₯Έ λ³€μˆ˜ plus 에도 κ·ΈλŒ€λ‘œ ν• λ‹Ήν•  수 μžˆλ‹€.

  • ν•¨μˆ˜ λ³€μˆ˜λ₯Ό μ‚¬μš©ν•΄ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  수 μžˆλ‹€.

ν•¨μˆ˜ 이름을 ν¬ν•¨ν•˜μ—¬ μž‘μ„±ν•  μˆ˜λ„ μžˆλŠ”λ° μ΄λŸ¬ν•œ ν•¨μˆ˜λ₯Ό κΈ°λͺ… ν•¨μˆ˜λΌ ν•œλ‹€.

var add = function sum(x, y) {    return x + y;};
console.log(add(3, 4)); // 7console.log(sum(3, 4)); // Error: sum is not defined

sum(3,4) 의 호좜이 Error κ°€ λ°œμƒν•˜λŠ”λ° ν•¨μˆ˜ ν‘œν˜„μ‹μ— μ‚¬μš©λœ ν•¨μˆ˜λͺ…은 μ™ΈλΆ€μ½”λ“œμ—μ„œ μ ‘κ·Ό λΆˆκ°€ν•˜λ‹€.

ν•¨μˆ˜λͺ…은 ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ μž¬κ·€μ μœΌλ‘œ ν˜ΈμΆœν•˜κ±°λ‚˜ λ””λ²„κ±°μ—μ„œ ν•¨μˆ˜λ₯Ό ꡬ뢄할 λ•Œ μ‚¬μš©ν•œλ‹€.

// ν•¨μˆ˜ λ‚΄λΆ€ μž¬κ·€μ  호좜 μ˜ˆμ‹œvar factorialVar = function factorial(n) {    if (n <= 1) {        return 1;    }    return n * factorial(n - 1);};
console.log(factorialVar(3));

μœ„μ—μ„œ ν•¨μˆ˜ μ„ μ–Έλ¬ΈμœΌλ‘œ μ •μ˜ν•œ κ²½μš°μ— ν•¨μˆ˜λͺ…μœΌλ‘œ ν˜ΈμΆœν•˜μ—¬ ν˜Όλž€μŠ€λŸ¬μšΈ 수 μžˆλŠ”λ°, ν•¨μˆ˜ μ„ μ–Έλ¬ΈμœΌλ‘œ μ •μ˜ν•œ ν•¨μˆ˜λŠ” λ‹€μŒκ³Ό 같은 ν•¨μˆ˜ ν‘œν˜„μ‹ ν˜•νƒœλ‘œ λ³€κ²½λ˜κΈ° λ•Œλ¬Έμ΄λ‹€.

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

ν•¨μˆ˜ 이름과 ν•¨μˆ˜ λ³€μˆ˜μ˜ 이름이 add 둜 κ°™μœΌλ―€λ‘œ μ‹€μ œλ‘œλŠ” add ν•¨μˆ˜ λ³€μˆ˜λ‘œ ν•¨μˆ˜μ™ΈλΆ€μ—μ„œ 호좜이 κ°€λŠ₯ν•˜κ²Œ 된 것이닀.


☝ ν•¨μˆ˜ μ„ μ–Έλ¬Έκ³Ό ν•¨μˆ˜ ν‘œν˜„μ‹μ—μ„œ μ„Έλ―Έμ½œλ‘ 

ν•¨μˆ˜ μ„ μ–Έλ¬ΈμœΌλ‘œ ν•¨μˆ˜λ₯Ό μ •μ˜ν•  λ•ŒλŠ” ν•¨μˆ˜ 끝에 μ„Έλ―Έμ½œλ‘ μ„ λ”°λ‘œ 뢙이지 μ•Šκ³ ,

ν•¨μˆ˜ ν‘œν˜„μ‹μœΌλ‘œ ν•¨μˆ˜λ₯Ό μ •μ˜ν•  λ•ŒλŠ” ν•¨μˆ˜ 끝에 μ„Έλ―Έμ½œλ‘ μ„ λΆ™μ΄λŠ” 것을 ꢌμž₯ν•œλ‹€.

일반적인 ν•˜λ‚˜μ˜ κ΄€μŠ΅μ΄λ‹€.


Function() μƒμ„±μž ν•¨μˆ˜#

JS의 ν•¨μˆ˜λ„ Function() μ΄λΌλŠ” κΈ°λ³Έ λ‚΄μž₯ μƒμ„±μž ν•¨μˆ˜λ‘œλΆ€ν„° μƒμ„±λœ 객체이닀.

μ•žμ„œ μ‚΄νŽ΄λ³Έ ν•¨μˆ˜ μ„ μ–Έλ¬Έμ΄λ‚˜ ν•¨μˆ˜ ν‘œν˜„μ‹ 방식도 κ²°κ΅­ λ‚΄λΆ€μ μœΌλ‘œλŠ” Function() μƒμ„±μž ν•¨μˆ˜λ‘œ μƒμ„±λœλ‹€.

new Function (arg1, arg2, ..., argN, functionBody)
- arg1, arg2, ... , argN - ν•¨μˆ˜μ˜ λ§€κ°œλ³€μˆ˜- functionBody - ν•¨μˆ˜κ°€ 호좜될 λ•Œ 싀행될 μ½”λ“œλ₯Ό ν¬ν•¨ν•œ λ¬Έμžμ—΄
var add = new Function('x', 'y', 'return x + y');console.log(add(3, 4)); // 7

이 방법은 자주 μ‚¬μš©λ˜μ§€ μ•ŠμœΌλ―€λ‘œ 상식 μˆ˜μ€€μœΌλ‘œ μ•Œκ³  λ„˜μ–΄κ°€μž.


ν™”μ‚΄ν‘œ ν•¨μˆ˜(arrow function)#

ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” ES6μ—μ„œ μΆ”κ°€λœ λ¬Έλ²•μœΌλ‘œ function ν‚€μ›Œλ“œ μ‚¬μš©λ³΄λ‹€ κ°„λ‹¨ν•˜κ²Œ λ§Œλ“€μˆ˜μžˆλ‹€. ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” 항상 읡λͺ… ν•¨μˆ˜μ΄λ‹€.

var add = (x, y) => {    return x + y;};
var add = (x, y) => x + y;

add ν•¨μˆ˜λ₯Ό 이처럼 κ°„λ‹¨ν•˜κ²Œ μž‘μ„±ν•  수 μžˆλ‹€. ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” ν•¨μˆ˜ bodyκ°€ ν•œ μ€„μΌλ•Œ , {} λ₯Ό μƒλž΅ν•˜λ©΄ return ν‚€μ›Œλ“œλ₯Ό μƒλž΅ν•œλ‹€. ( {} λ₯Ό μ‚¬μš©ν•˜λ©΄ return ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•΄μ•Ό ν•œλ‹€.)

상황에 따라 더 κ°„λ‹¨ν•˜κ²Œ μž‘μ„±ν•  수 μžˆλŠ” λͺ‡ 가지 κ·œμΉ™μ΄ μžˆλ‹€.

// λ§€κ°œλ³€μˆ˜κ°€ μ—†λŠ” 경우var foo = () => console.log('bar');foo(); // bar
// λ§€κ°œλ³€μˆ˜κ°€ ν•˜λ‚˜μΈ 경우 () μƒλž΅ κ°€λŠ₯var foo = (x) => x;console.log(foo('bar')); // bar
// λ§€κ°œλ³€μˆ˜κ°€ μ—¬λŸ¬ 개인 경우var foo = (a, b) => a + b;console.log(foo(1, 2)); // 3
// ν•¨μˆ˜ bodyκ°€ μ—¬λŸ¬ 쀄일 경우var foo = (a, b) => {    var c = 3;    return a + b + c;};console.log(foo(1, 2)); // 6
// 객체λ₯Ό λ°˜ν™˜ν•  λ•Œvar foo = () => ({a: 1, b: 2, c: 3});console.log(foo()); // { a: 1, b: 2, c: 3 }

콜백 ν•¨μˆ˜, this ν‚€μ›Œλ“œ λ“±μ—μ„œ 차이가 μžˆλŠ”λ°, μ΄λŠ” 좔후에 기술


ν•¨μˆ˜ ν˜Έμ΄μŠ€νŒ…(hoisting)#

ν•¨μˆ˜ μ„ μ–Έλ¬Έ ν˜•νƒœλ‘œ μ •μ˜ν•œ ν•¨μˆ˜μ˜ 유효 λ²”μœ„λŠ” μ½”λ“œμ˜ 맨 μ²˜μŒλΆ€ν„° μ‹œμž‘ν•œλ‹€. 이λ₯Ό ν•¨μˆ˜ ν˜Έμ΄μŠ€νŒ…μ΄λΌκ³  λΆ€λ₯Έλ‹€.

μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œλŠ” λ³€μˆ˜ 생성과 μ΄ˆκΈ°ν™”μ˜ μž‘μ—…μ΄ λΆ„λ¦¬λΌμ„œ 이루어지기 λ•Œλ¬Έμ— ν•¨μˆ˜ν‘œν˜„μ‹, Function() μƒμ„±μž ν•¨μˆ˜, ν™”μ‚΄ν‘œ ν•¨μˆ˜μ—μ„œλŠ” μΌμ–΄λ‚˜μ§€ μ•ŠλŠ”λ‹€.

μ΄λŸ¬ν•œ ν•¨μˆ˜ ν˜Έμ΄μŠ€νŒ…μ΄ μ½”λ“œμ˜ ꡬ쑰λ₯Ό μ–΄μ§€λŸ½νž 수 μžˆμœΌλ―€λ‘œ λ§Žμ€ μ‚¬λžŒλ“€μ΄ ν•¨μˆ˜ μ„ μ–Έ 방식을 μΆ”μ²œν•˜μ§€ μ•ŠκΈ°λ„ ν•œλ‹€.


ν•¨μˆ˜ 객체#

ν•¨μˆ˜λ„ 객체닀#

JSμ—μ„œλŠ” ν•¨μˆ˜λ„ 객체둜, κΈ°λ³Έ κΈ°λŠ₯인 μ½”λ“œ μ‹€ν–‰λΏλ§Œ μ•„λ‹ˆλΌ ν•¨μˆ˜ μžμ²΄κ°€ 일반 객체처럼 ν”„λ‘œνΌν‹°λ“€μ„ κ°€μ§ˆ 수 μžˆλ‹€.

function add(x, y) {    return x + y;}
add.result = add(3, 2);add.status = 'OK';
console.log(add.result);console.log(add.status);

add() ν•¨μˆ˜μ— 마치 일반 객체처럼 ν”„λ‘œνΌν‹°λ₯Ό λ™μ μœΌλ‘œ μƒμ„±ν•˜κ³  μ ‘κ·Όν•  수 μžˆλ‹€.

ν•¨μˆ˜λŠ” κ°’μœΌλ‘œ μ·¨κΈ‰λœλ‹€#

ν•¨μˆ˜κ°€ 일반 객체처럼 취급될 수 μžˆμœΌλ―€λ‘œ λ‹€μŒκ³Ό 같은 λ™μž‘μ΄ λͺ¨λ‘ κ°€λŠ₯ν•˜λ‹€.

  • λ¦¬ν„°λŸ΄μ— μ˜ν•΄ 생성

  • λ³€μˆ˜λ‚˜ λ°°μ—΄μ˜ μš”μ†Œ, 객체의 ν”„λ‘œνΌν‹° 등에 ν• λ‹Ή κ°€λŠ₯

  • ν•¨μˆ˜μ˜ 인자둜 전달 κ°€λŠ₯

  • ν•¨μˆ˜μ˜ λ¦¬ν„΄κ°’μœΌλ‘œ 리턴 κ°€λŠ₯

  • λ™μ μœΌλ‘œ ν”„λ‘œνΌν‹°λ₯Ό 생성 및 ν• λ‹Ή κ°€λŠ₯

☝ μ΄λŸ¬ν•œ κΈ°λŠ₯이 λͺ¨λ‘ κ°€λŠ₯ν•œ 객체λ₯Ό 일급 객체(First Class)라고 ν•œλ‹€. μ΄λŸ¬ν•œ νŠΉμ„±μœΌλ‘œ ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°μ΄ κ°€λŠ₯ν•˜λ‹€.

λ³€μˆ˜λ‚˜ ν”„λ‘œνΌν‹°μ˜ κ°’μœΌλ‘œ ν• λ‹Ή#

// λ³€μˆ˜μ— ν•¨μˆ˜ ν• λ‹Ήvar bar = function () {    return 100;};console.log(bar()); // 100
// ν”„λ‘œνΌν‹°μ— ν•¨μˆ˜ ν• λ‹Ήvar obj = {};obj.baz = function () {    return 200;};console.log(obj.baz()); // 200

ν•¨μˆ˜ 인자둜 전달#

// ν•¨μˆ˜ ν‘œν˜„μ‹μœΌλ‘œ foo() ν•¨μˆ˜ 생성var foo = function (func) {    func(); // 인자둜 받은 func() ν•¨μˆ˜ 호좜};
// foo() ν•¨μˆ˜ μ‹€ν–‰foo(function () {    console.log('Function can be used as the argument.');});

리턴 κ°’μœΌλ‘œ ν™œμš©#

// ν•¨μˆ˜λ₯Ό λ¦¬ν„΄ν•˜λŠ” foo() ν•¨μˆ˜ μ •μ˜var foo = function () {    return function () {        console.log('this function is the return value.');    };};
var bar = foo();bar();

ν•¨μˆ˜ 객체의 κΈ°λ³Έ ν”„λ‘œνΌν‹°#

ν•¨μˆ˜ μ—­μ‹œ 일반적인 객체의 κΈ°λŠ₯에 μΆ”κ°€μ μœΌλ‘œ, ν˜ΈμΆœλμ„ λ•Œ μ •μ˜λœ μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λŠ”κΈ°λŠ₯을 가지고 μžˆλ‹€.

일반 κ°μ²΄μ™€λŠ” λ‹€λ₯΄κ²Œ μΆ”κ°€λ‘œ ν•¨μˆ˜ 객체만의 ν‘œμ€€ ν”„λ‘œνΌν‹°κ°€ μ •μ˜λ˜μ–΄ μžˆλ‹€.

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

2020-03-03-4-ν•¨μˆ˜μ™€-ν”„λ‘œν† νƒ€μž…-체이닝-1-image-0

κ²°κ³Όλ₯Ό μ‚΄νŽ΄λ³΄λ©΄, arguments , caller , length λ“±κ³Ό 같은 λ‹€μ–‘ν•œ ν”„λ‘œνΌν‹°κ°€κΈ°λ³Έμ μœΌλ‘œ μƒμ„±λœ 것을 확인할 수 μžˆλ‹€. 이 ν”„λ‘œνΌν‹°λ“€μ΄ ν‘œμ€€ ν”„λ‘œνΌν‹°λ‹€.

  • name : ν•¨μˆ˜ 이름 (읡λͺ… ν•¨μˆ˜μΈ 경우 빈 λ¬Έμžμ—΄)

  • caller : μžμ‹ μ„ ν˜ΈμΆœν•œ ν•¨μˆ˜.

  • arguments : ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•Œ μ „λ‹¬λœ μΈμžκ°’.

  • length : ν•¨μˆ˜λ₯Ό μž‘μ„±ν•  λ•Œ μ •μ˜ν•œ 인자 개수.

  • prototype : 이 ν•¨μˆ˜κ°€ μƒμ„±μžλ‘œ μ‚¬μš©λ  λ•Œ 이 ν•¨μˆ˜λ₯Ό 톡해 μƒμ„±λœ 객체의 λΆ€λͺ¨μ—­ν• μ„ ν•˜λŠ” ν”„λ‘œν† νƒ€μž… 객체

  • __proto__ : μžμ‹ μ˜ λΆ€λͺ¨ 역할을 ν•˜λŠ” ν”„λ‘œν† νƒ€μž… 객체λ₯Ό κ°€λ¦¬ν‚€λŠ” [[Prototype]] ( Function.prototype )

☝ 좜λ ₯값을 확인해보면 ν¬λ‘¬μ—μ„œλŠ” Empty() ν•¨μˆ˜

Function.prototype 객체의 ν”„λ‘œν† νƒ€μž… κ°μ²΄λŠ”?

λͺ¨λ“  ν•¨μˆ˜λ“€μ˜ λΆ€λͺ¨ 객체인 Function.prototype 의 λΆ€λͺ¨λŠ” μ˜ˆμ™Έμ μœΌλ‘œ Object.prototype 객체


ν•¨μˆ˜ 객체와 ν”„λ‘œν† νƒ€μž… κ°μ²΄μ™€μ˜ 관계#

2020-03-03-4-ν•¨μˆ˜μ™€-ν”„λ‘œν† νƒ€μž…-체이닝-1-image-1

myFunction() ν•¨μˆ˜μ˜ ν”„λ‘œν† νƒ€μž…, myFunction.prototype κ°μ²΄λŠ” constructor 와 __proto__ λΌλŠ” 두 개의 ν”„λ‘œνΌν‹°κ°€ μžˆλ‹€.

myFunction.prototype.constructor 의 값을 좜λ ₯해보면, ν”„λ‘œν† νƒ€μž… 객체와 λ§€ν•‘λœν•¨μˆ˜λ₯Ό λ³Ό 수 μžˆλŠ”λ° myFunction() ν•¨μˆ˜λ₯Ό 가리킀고 μžˆλ‹€.

2020-03-03-4-ν•¨μˆ˜μ™€-ν”„λ‘œν† νƒ€μž…-체이닝-1-image-2


참고 자료#

πŸ”— JavaScript - ν™”μ‚΄ν‘œ ν•¨μˆ˜(Arrow function)