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

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

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

ν•¨μˆ˜μ˜ λ‹€μ–‘ν•œ ν˜•νƒœ#

콜백 ν•¨μˆ˜#

콜백 ν•¨μˆ˜λŠ” κ°œλ°œμžκ°€ 단지 ν•¨μˆ˜λ₯Ό λ“±λ‘ν•˜κΈ°λ§Œ ν•˜κ³ , μ΄λ²€νŠΈκ°€ λ°œμƒν–ˆκ±°λ‚˜ νŠΉμ • μ‹œμ μ— λ„λ‹¬ν–ˆμ„ λ•Œ μ‹œμŠ€ν…œμ—μ„œ ν˜ΈμΆœλ˜λŠ” ν•¨μˆ˜λ₯Ό λ§ν•œλ‹€. λ˜ν•œ νŠΉμ • ν•¨μˆ˜μ˜ 인자둜 λ„˜κ²¨μ„œ , μ½”λ“œ λ‚΄λΆ€μ—μ„œ ν˜ΈμΆœλ˜λŠ” ν•¨μˆ˜ λ˜ν•œ 콜백 ν•¨μˆ˜κ°€ 될 수 μžˆλ‹€.

λŒ€ν‘œμ μΈ 콜백 ν•¨μˆ˜μ˜ μ‚¬μš© μ˜ˆκ°€ JSμ—μ„œμ˜ 이벀트 ν•Έλ“€λŸ¬ μ²˜λ¦¬μ΄λ‹€. μ›ΉνŽ˜μ΄μ§€κ°€ λ‘œλ“œλ˜κ±°λ‚˜ ν‚€λ³΄λ“œκ°€ μž…λ ₯λ˜λŠ” λ“±μ˜ DOM μ΄λ²€νŠΈκ°€ λ°œμƒν•  경우, λΈŒλΌμš°μ €λŠ” μ •μ˜λœ DOM μ΄λ²€νŠΈμ— ν•΄λ‹Ήν•˜λŠ” 이벀트 ν•Έλ“€λŸ¬λ₯Ό μ‹€ν–‰μ‹œν‚¨λ‹€. μ΄λŸ¬ν•œ 이벀트 ν•Έλ“€λŸ¬μ— 콜백 ν•¨μˆ˜κ°€λ“±λ‘ν–ˆλ‹€λ©΄, 콜백 ν•¨μˆ˜λŠ” μ΄λ²€νŠΈκ°€ λ°œμƒν•  λ•Œλ§ˆλ‹€ λΈŒλΌμš°μ €μ— μ˜ν•΄ μ‹€ν–‰λ˜κ²Œ λœλ‹€.

<!DOCTYPE html><html>    <body>        <script>            // νŽ˜μ΄μ§€ λ‘œλ“œ μ‹œ 호좜될 콜백 ν•¨μˆ˜            window.onload = function () {                alert('This is the callback function.');            };        </script>    </body></html>

μ¦‰μ‹œ μ‹€ν–‰ ν•¨μˆ˜#

ν•¨μˆ˜λ₯Ό μ •μ˜ν•¨κ³Ό λ™μ‹œμ— λ°”λ‘œ μ‹€ν–‰ν•˜λŠ” ν•¨μˆ˜λ₯Ό μ¦‰μ‹œ μ‹€ν–‰ ν•¨μˆ˜λΌ ν•œλ‹€.

(function (name) {    console.log('This is the immediate function -->' + name);})('foo');

[μ‹€ν–‰ κ²°κ³Ό]

This is the immediate function --> foo

μ¦‰μ‹œ μ‹€ν–‰ ν•¨μˆ˜λŠ” ν•¨μˆ˜ λ¦¬ν„°λŸ΄μ„ κ΄„ν˜Έ () 둜 감싼닀. 그런 λ‹€μŒ ν•¨μˆ˜κ°€ λ°”λ‘œ 호좜될수 μžˆλ„λ‘ () κ΄„ν˜Έ μŒμ„ μΆ”κ°€ν•œλ‹€. 이 λ•Œ κ΄„ν˜Έ μ•ˆμ— 값을 μΆ”κ°€ν•΄ 인자λ₯Ό λ„˜κ²¨μ€„μˆ˜μžˆλ‹€.

μ΄λ ‡κ²Œ μ¦‰μ‹œ μ‹€ν–‰ ν•¨μˆ˜λ₯Ό λ§Œλ“€λ©΄, 이후에 같은 ν•¨μˆ˜λ₯Ό λ‹€μ‹œ ν˜ΈμΆœν•  수 μ—†λ‹€. μ΅œμ΄ˆν•œλ²ˆμ˜ μ‹€ν–‰λ§Œμ„ ν•„μš”λ‘œ ν•˜λŠ” μ΄ˆκΈ°ν™” μ½”λ“œ 뢀뢄에 μ‚¬μš©ν•  수 μžˆλ‹€.

jQuery와 같은 μžλ°”μŠ€ν¬λ¦½νŠΈ λΌμ΄λΈŒλŸ¬λ¦¬λ‚˜ ν”„λ ˆμž„μ›Œν¬ μ†ŒμŠ€λ₯Ό μ‚΄νŽ΄λ³΄λ©΄, μ¦‰μ‹œ μ‹€ν–‰ ν•¨μˆ˜ ν˜•νƒœλ‘œ κ΅¬μ„±λ˜μ–΄ μžˆλŠ”λ° μ΄λŠ” μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ λ³€μˆ˜ 유효 λ²”μœ„ νŠΉμ„± λ•Œλ¬Έμ΄λ‹€.

μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œλŠ” ν•¨μˆ˜ 유효 λ²”μœ„λ₯Ό μ§€μ›ν•œλ‹€. 기본적으둜 μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” λ³€μˆ˜λ₯Ό μ„ μ–Έν•  λ•Œ μ „μ—­ 유효 λ²”μœ„λ₯Ό κ°€μ§€μ§€λ§Œ, ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ μ •μ˜λœ λ§€κ°œλ³€μˆ˜μ™€ λ³€μˆ˜λ“€μ€ν•¨μˆ˜ μ½”λ“œ λ‚΄λΆ€μ—μ„œλ§Œ μœ νš¨ν•˜λ‹€. (ν•¨μˆ˜ 내에 λ³€μˆ˜λŠ” var λ₯Ό μ‚¬μš©ν•΄μ•Ό μ „μ—­ 유효 λ²”μœ„λ₯Ό 갖지 μ•ŠλŠ”λ‹€.) 이것은 달리 λ§ν•˜λ©΄ ν•¨μˆ˜ μ™ΈλΆ€μ˜ μ½”λ“œμ—μ„œ ν•¨μˆ˜ λ‚΄λΆ€μ˜ λ³€μˆ˜λ₯Ό μ•‘μ„ΈμŠ€ν•˜λŠ” 게 λΆˆκ°€λŠ₯ ν•˜λ‹€λŠ” λœ»μ΄λ‹€.

λ”°λΌμ„œ 라이브러리 μ½”λ“œλ₯Ό μ¦‰μ‹œ μ‹€ν–‰ ν•¨μˆ˜ 내뢀에 μ •μ˜ν•˜λ©΄, 라이브러리 λ‚΄μ˜ λ³€μˆ˜λ“€μ€ ν•¨μˆ˜ μ™ΈλΆ€μ—μ„œ μ ‘κ·Όν•  수 μ—†κ³ , μ „μ—­ λ„€μž„μŠ€νŽ˜μ΄μŠ€λ₯Ό λ”λŸ½νžˆμ§€ μ•Šμ•„ λ³€μˆ˜ 이름 좩돌이 λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€.


  • ν•¨μˆ˜ 내에 var 문을 μ‚¬μš©ν•΄ λ³€μˆ˜ 이름을 μ μš©ν•  경우
var num = 10;
function myFunc() {    var num = 20;}
myFunc();
console.log(num); // 10

  • ν•¨μˆ˜ 내에 var 문을 μ‚¬μš©ν•˜μ§€ μ•Šμ„ 경우
var num = 10;
function myFunc() {    num = 20;}
myFunc();
console.log(num); // 20

λ‚΄λΆ€ ν•¨μˆ˜#

JSμ—μ„œλŠ” ν•¨μˆ˜ μ½”λ“œ λ‚΄λΆ€μ—μ„œ ν•¨μˆ˜ μ •μ˜κ°€ κ°€λŠ₯ν•˜λ‹€. μ΄λŸ¬ν•œ ν•¨μˆ˜λ₯Ό λ‚΄λΆ€ ν•¨μˆ˜(inner function)이라 ν•œλ‹€.

// parent() ν•¨μˆ˜ μ •μ˜function parent() {    var a = 100;    var b = 200;
    // child() λ‚΄λΆ€ ν•¨μˆ˜ μ •μ˜    function child() {        var b = 300;
        console.log(a);        console.log(b);    }    child();}
parent();child();

[좜λ ₯ κ²°κ³Ό]

100300Uncaught ReferenceError: child is not defined

λ‚΄λΆ€ ν•¨μˆ˜μ—μ„œλŠ” μžμ‹ μ„ λ‘˜λŸ¬μ‹Ό λΆ€λͺ¨ ν•¨μˆ˜ λ³€μˆ˜μ— μ ‘κ·Ό κ°€λŠ₯ν•˜λ‹€. (μŠ€μ½”ν”„ 체이닝 )

λ‚΄λΆ€ ν•¨μˆ˜λŠ” 일반적으둜 μžμ‹ μ΄ μ •μ˜λœ λΆ€λͺ¨ ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œλ§Œ 호좜이 κ°€λŠ₯ν•˜λ‹€.

그런데, λΆ€λͺ¨ ν•¨μˆ˜μ—μ„œ λ‚΄λΆ€ ν•¨μˆ˜λ₯Ό μ™ΈλΆ€λ‘œ 리턴할 경우, λΆ€λͺ¨ ν•¨μˆ˜ λ°–μ—μ„œλ„ λ‚΄λΆ€ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λŠ” 것이 κ°€λŠ₯ν•˜λ‹€.

function parent() {    var a = 100;    // child() λ‚΄λΆ€ ν•¨μˆ˜    var child = function () {        console.log(a);    };
    // child() ν•¨μˆ˜ λ°˜ν™˜    return child;}
var inner = parent();inner();

[좜λ ₯ κ²°κ³Ό]

100

이와 같이 싀행이 λλ‚œ parent() 와 같은 λΆ€λͺ¨ ν•¨μˆ˜ μŠ€μ½”ν”„μ˜ λ³€μˆ˜λ₯Ό μ°Έμ‘°ν•˜λŠ” inner() 와 같은 ν•¨μˆ˜λ₯Ό ν΄λ‘œμ €λΌκ³  ν•œλ‹€.


ν•¨μˆ˜λ₯Ό λ¦¬ν„΄ν•˜λŠ” ν•¨μˆ˜#

JSμ—μ„œλŠ” ν•¨μˆ˜λ„ 일급 κ°μ²΄μ΄λ―€λ‘œ 일반 κ°’μ²˜λŸΌ ν•¨μˆ˜ 자체λ₯Ό 리턴할 수 μžˆλŠ”λ°, 이λ₯Όν†΅ν•΄ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•¨κ³Ό λ™μ‹œμ— λ‹€λ₯Έ ν•¨μˆ˜λ‘œ λ°”κΎΈκ±°λ‚˜ 자기 μžμ‹ μ„ μž¬μ •μ˜ν•˜λŠ” ν•¨μˆ˜λ₯Όκ΅¬ν˜„ν•  수 μžˆλ‹€.

var self = function () {    console.log('a');    return function () {        console.log('b');    };};self = self(); // aself(); // b

ν•¨μˆ˜ 호좜과 this#

arguments 객체#

JSμ—μ„œλŠ” ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•Œ ν•¨μˆ˜ ν˜•μ‹μ— 맞좰 인자λ₯Ό λ„˜κΈ°μ§€ μ•Šλ”λΌλ„ μ—λŸ¬κ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€.

function func(arg1, arg2) {    console.log(arg1, arg2);}
func(); // undefined undefinedfunc(1); // 1 undefinedfunc(1, 2); // 1 2func(1, 2, 3); // 1 2

JSμ—μ„œλŠ” μ •μ˜λœ ν•¨μˆ˜ μΈμžμ™€ λ‹€λ₯΄κ²Œ λ„˜κΈ°λ”λΌλ„ μ—λŸ¬κ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€.

ν•¨μˆ˜μ˜ μΈμžλ³΄λ‹€ 적게 ν•¨μˆ˜λ₯Ό 호좜 ν–ˆμ„ κ²½μš°μ—λŠ” undefined κ°€ ν• λ‹Ήλ˜κ³ , 많게 호좜 ν–ˆμ„ κ²½μš°μ—λŠ” λ¬΄μ‹œλœλ‹€.

μ΄λŸ¬ν•œ νŠΉμ„± λ•Œλ¬Έμ— λŸ°νƒ€μž„ μ‹œμ— 호좜된 인자의 개수λ₯Ό ν™•μΈν•˜κ³  λ™μž‘μ„ λ‹€λ₯΄κ²Œ ν•΄μ€˜μ•Ό ν•  κ²½μš°κ°€ μžˆλŠ”λ°, arguments 객체가 이λ₯Ό κ°€λŠ₯μΌ€ ν•œλ‹€.

JSμ—μ„œλŠ” ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•Œ μ•”λ¬΅μ μœΌλ‘œ arguments 객체가 λ‚΄λΆ€λ‘œ μ „λ‹¬λœλ‹€.

arguments κ°μ²΄λŠ” ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•Œ λ„˜κΈ΄ μΈμžλ“€μ΄ λ°°μ—΄ ν˜•νƒœλ‘œ μ €μž₯된 객체λ₯Ό μ˜λ―Έν•œλ‹€. νŠΉμ΄ν•œ 점은 이 객체가 μœ μ‚¬ λ°°μ—΄ κ°μ²΄λΌλŠ” 점이닀.

function add(a, b) {    console.dir(arguments);    return a + b;}
console.log(add(1)); // NaNconsole.log(add(1, 2)); // 3console.log(add(1, 2, 3)); // 3

length ν”„λ‘œνΌν‹°κ°€ 있기 λ•Œλ¬Έμ— λ°°μ—΄κ³Ό μœ μ‚¬ν•˜κ²Œ λ™μž‘ν•˜μ§€λ§Œ, λ°°μ—΄ λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν• κ²½μš° μ—λŸ¬κ°€ λ°œμƒν•œλ‹€.

arguments κ°μ²΄λŠ” λ§€κ°œλ³€μˆ˜ κ°œμˆ˜κ°€ μ •ν™•ν•˜κ²Œ 정해지지 μ•Šμ€ ν•¨μˆ˜λ₯Ό κ΅¬ν˜„ν•˜κ±°λ‚˜ μ „λ‹¬λœ 인자의 κ°œμˆ˜μ— 닀라 μ„œλ‘œ λ‹€λ₯Έ 처리λ₯Ό ν•΄μ€˜μ•Ό ν•˜λŠ” ν•¨μˆ˜λ₯Ό κ°œλ°œν•˜λŠ” 데 μœ μš©ν•˜κ²Œμ‚¬μš©ν•  수 μžˆλ‹€.

function sum() {    var result = 0;
    for (var i = 0; i < arguments.length; i++) {        result += arguments[i];    }
    return result;}
console.log(sum(1, 2, 3)); // 6console.log(sum(1, 2, 3, 4, 5, 6, 7, 8, 9)); // 45

호좜 νŒ¨ν„΄κ³Ό this 바인딩#

JSμ—μ„œλŠ” ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•Œ κΈ°μ‘΄ λ§€κ°œλ³€μˆ˜λ‘œ μ „λ‹¬λ˜λŠ” μΈμžκ°’μ— 더해 arguments 객체 및 this μΈμžκ°€ ν•¨μˆ˜ λ‚΄λΆ€λ‘œ μ•”λ¬΅μ μœΌλ‘œ μ „λ‹¬λœλ‹€.

JS의 μ—¬λŸ¬ 가지 ν•¨μˆ˜κ°€ ν˜ΈμΆœλ˜λŠ” 방식(호좜 νŒ¨ν„΄)에 따라 this κ°€ λ‹€λ₯Έ 객체λ₯Όμ°Έμ‘°ν•˜κΈ°( this 바인딩) λ•Œλ¬Έμ— μ΄ν•΄ν•˜κΈ° μ–΄λ ΅λ‹€.


객체의 λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•  λ•Œ this 바인딩#

객체의 ν”„λ‘œνΌν‹°κ°€ ν•¨μˆ˜μΌ 경우 λ©”μ†Œλ“œλΌκ³  ν•œλ‹€. λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•  λ•Œ λ©”μ†Œλ“œ λ‚΄λΆ€ μ½”λ“œμ—μ„œ μ‚¬μš©λœ this λŠ” λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•œ 객체둜 λ°”μΈλ”©λœλ‹€.

var myObject = {    name: 'foo',    sayName: function () {        console.log(this.name);    },};
var otherObject = {    name: 'bar',};
otherObject.sayName = myObject.sayName;
myObject.sayName(); // foootherObject.sayName(); // bar

이 μ˜ˆμ œμ—μ„œ sayName() λ©”μ†Œλ“œμ— μ‚¬μš©λœ this λŠ” μžμ‹ μ„ ν˜ΈμΆœν•œ 객체에 λ°”μΈλ”©λ˜μ–΄, myObject μ—μ„œ ν˜ΈμΆœν•œ κ²½μš°λŠ” foo , otherObject μ—μ„œ ν˜ΈμΆœν•œ κ²½μš°λŠ” bar κ°€ 좜λ ₯λœλ‹€.


ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•Œ this 바인딩#

ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ©΄, ν•¨μˆ˜ μ½”λ“œ λ‚΄λΆ€μ—μ„œ μ‚¬μš©λœ this λŠ” μ „μ—­ 객체에 λ°”μΈλ”©λœλ‹€. λΈŒλΌμš°μ €μ—μ„œ μžλ°”μŠ€ν¬λ¦½νŠΈλ₯Ό μ‹€ν–‰ν•˜λŠ” 경우 μ „μ—­ κ°μ²΄λŠ” window 객체가 λœλ‹€.

즉 μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ λͺ¨λ“  μ „μ—­ λ³€μˆ˜λŠ” μ „μ—­ 객체( window )의 ν”„λ‘œνΌν‹°μ΄λ‹€.

var foo = "I'm foo";
console.log(foo); // I'm fooconsole.log(window.foo); // I'm foo

ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•Œ this 바인딩

var test = 'This is test';console.log(window.test);
// sayFoo() ν•¨μˆ˜var sayFoo = function () {    console.log(this.test); // sayFoo() ν•¨μˆ˜ 호좜 μ‹œ thisλŠ” μ „μ—­ 객체에 λ°”μΈλ”©λœλ‹€.};
sayFoo();

μ΄λ ‡κ²Œ ν•¨μˆ˜ ν˜ΈμΆœμ‹œ this κ°€ μ „μ—­ 객체에 λ°”μΈλ”©λ˜λŠ” 것은 λ‚΄λΆ€ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν–ˆμ„ κ²½μš°μ—λ„ κ·ΈλŒ€λ‘œ μ μš©λ˜λ―€λ‘œ μ£Όμ˜ν•΄μ•Ό ν•œλ‹€.

var value = 100;
var myObject = {    varlue: 1,    func1: function () {        this.value += 1;        console.log('func1() called. this.value : ' + this.value);
        func2 = function () {            this.value += 1;            console.log('func2 called. this.value : ' + this.value);
            func3 = function () {                this.value += 1;                console.log('func3() called. this.value : ' + this.value);            };            func3();        };        func2();    },};myObject.func1();

λ‚΄λΆ€ ν•¨μˆ˜ ν˜ΈμΆœλ„ ν•¨μˆ˜ 호좜둜 μ·¨κΈ‰λ˜λ―€λ‘œ func2() , func3() ν˜ΈμΆœμ‹œμ— this λŠ”μ „μ—­ 객체에 λ°”μΈλ”©λ˜μ–΄ window.value 에 1을 λ”ν•œ 값이 λ‚˜μ˜¨λ‹€.

[좜λ ₯ κ²°κ³Ό]

func1() called - this.value : 2func2() called - this.value : 101func3() called - this.value : 102

μ΄λ ‡κ²Œ λ‚΄λΆ€ ν•¨μˆ˜κ°€ this λ₯Ό μ°Έμ‘°ν•˜λŠ” ν•œκ³„λ₯Ό κ·Ήλ³΅ν•˜λ €λ©΄ λΆ€λͺ¨ ν•¨μˆ˜μ˜ this λ₯Ό λ‚΄λΆ€ ν•¨μˆ˜κ°€ μ ‘κ·Ό κ°€λŠ₯ν•œ λ‹€λ₯Έ λ³€μˆ˜μ— μ €μž₯ν•˜λŠ” 방법이 μ‚¬μš©λœλ‹€. μ΄λŸ¬ν•œ 경우 λ³€μˆ˜μ˜μ΄λ¦„μ„ 관둀상 that 이라 ν•œλ‹€.

var value = 100;
var myObject = {    varlue: 1,    func1: function () {        var that = this;
        this.value += 1;        console.log('func1() called. this.value : ' + this.value);
        func2 = function () {            that.value += 1;            console.log('func2 called. this.value : ' + that.value);
            func3 = function () {                that.value += 1;                console.log('func3() called. this.value : ' + that.value);            };            func3();        };        func2();    },};myObject.func1();

[좜λ ₯ κ²°κ³Ό]

func1() called - this.value : 2func2() called - this.value : 3func3() called - this.value : 4

μƒμ„±μž ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•Œ this 바인딩#

객체 μƒμ„±ν•˜λŠ” 방법은 크게 두가지

  • 객체 λ¦¬ν„°λŸ΄

  • μƒμ„±μž ν•¨μˆ˜ : κΈ°μ‘΄ ν•¨μˆ˜μ— new μ—°μ‚°μžλ₯Ό λΆ™μ—¬μ„œ ν˜ΈμΆœν•˜λ©΄ ν•΄λ‹Ή ν•¨μˆ˜κ°€ μƒμ„±μž ν•¨μˆ˜λ‘œ λ™μž‘


일반 ν•¨μˆ˜μ— new λ₯Ό λΆ™μ—¬ ν˜ΈμΆœν•˜λ©΄ μ›μΉ˜ μ•ŠλŠ” μƒμ„±μž ν•¨μˆ˜μ²˜λŸΌ λ™μž‘ν•  수 μžˆμœΌλ―€λ‘œ, νŠΉμ • ν•¨μˆ˜κ°€ μƒμ„±μž ν•¨μˆ˜λΌλ©΄ ν•¨μˆ˜ μ΄λ¦„μ˜ 첫 문자λ₯Ό λŒ€λ¬Έμžλ‘œ μ“°κΈ°λ₯Ό ꢌμž₯ .


μƒμ„±μž ν•¨μˆ˜μ˜ λ‚΄λΆ€ this λŠ” λ©”μ†Œλ“œ, ν•¨μˆ˜ 호좜 λ°©μ‹μ˜ this 바인딩과 λ‹€λ₯΄κ²Œ λ™μž‘ν•œλ‹€.


⭐ μƒμ„±μž ν•¨μˆ˜κ°€ λ™μž‘ν•˜λŠ” 방식

new μ—°μ‚°μžλ‘œ μžλ°”μŠ€ν¬λ¦½νŠΈ ν•¨μˆ˜λ₯Ό μƒμ„±μžλ‘œ ν˜ΈμΆœν•˜λ©΄ λ‹€μŒκ³Ό 같은 μˆœμ„œλ‘œ λ™μž‘ν•œλ‹€ .

  1. 빈 객체 생성 및 this 바인딩

    μƒμ„±μž ν•¨μˆ˜ μ½”λ“œκ°€ μ‹€ν–‰λ˜κΈ° μ „, 빈 객체가 생성(μƒμ„±μž ν•¨μˆ˜κ°€ μƒˆλ‘œ μƒμ„±ν•˜λŠ” 객체)되고 이 객체가 this 둜 λ°”μΈλ”©λœλ‹€. 이 κ°μ²΄λŠ” μžμ‹ μ„ μƒμ„±ν•œ μƒμ„±μž ν•¨μˆ˜μ˜ prototype ν”„λ‘œνΌν‹°κ°€ κ°€λ¦¬ν‚€λŠ” 객체λ₯Ό μžμ‹ μ˜ ν”„λ‘œν† νƒ€μž… κ°μ²΄λ‘œμ„€μ •ν•œλ‹€.

  2. this λ₯Ό ν†΅ν•œ ν”„λ‘œνΌν‹° 생성

    μ΄ν›„μ—λŠ” ν•¨μˆ˜ μ½”λ“œ λ‚΄λΆ€μ˜ this λ₯Ό 톡해 μ•žμ„œ μƒμ„±λœ 빈 객체에 λ™μ μœΌλ‘œ ν”„λ‘œνΌν‹°λ‚˜ λ©”μ†Œλ“œλ₯Ό μƒμ„±ν•œλ‹€.

  3. μƒμ„±λœ 객체 λ¦¬ν„΄μƒμ„±μž ν•¨μˆ˜μ—μ„œλŠ” 리턴문이 μ—†λŠ” 경우 this 둜 λ°”μΈλ”©λœ μƒˆλ‘œμƒμ„±λœ 객체가 λ¦¬ν„΄λœλ‹€. λͺ…μ‹œμ μœΌλ‘œ this λ₯Ό 리턴해도 κ²°κ³ΌλŠ” κ°™λ‹€. (μƒμ„±μžν•¨μˆ˜κ°€ μ•„λ‹ˆλΌλ©΄ 리턴값이 λͺ…μ‹œλ˜μ–΄ μžˆμ§€ μ•Šμ€ 경우 undefined κ°€ λ¦¬ν„΄λœλ‹€.)


// Person() μƒμ„±μž ν•¨μˆ˜var Person = function (name) {    // ν•¨μˆ˜ μ½”λ“œ μ‹€ν–‰ μ „    this.name = name;    // ν•¨μˆ˜ 리턴};
// foo 객체 생성var foo = new Person('foo');console.log(foo.name); // foo

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


⭐ 객체 λ¦¬ν„°λŸ΄ 방식과 μƒμ„±μž ν•¨μˆ˜λ₯Ό ν†΅ν•œ 객체 생성 λ°©μ‹μ˜ 차이

객체 λ¦¬ν„°λŸ΄ 방식은 같은 ν˜•νƒœμ˜ 객체λ₯Ό μž¬μƒμ„±ν•  수 μ—†λ‹€. 이에 λ°˜ν•΄ Person() μƒμ„±μž ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄ 같은 ν˜•νƒœμ˜ λ‹€λ₯Έ 객체λ₯Ό μ—¬λŸ¬κ°œ 생성할 수 μžˆλ‹€.


// 객체 λ¦¬ν„°λŸ΄ λ°©μ‹μœΌλ‘œ foo 객체 생성var foo = {    name: 'foo',    age: 35,    gender: 'man',};console.dir(foo);
// μƒμ„±μž ν•¨μˆ˜function Person(name, age, gender, position) {    this.name = name;    this.age = age;    this.gender = gender;}
// Person μƒμ„±μž ν•¨μˆ˜λ₯Ό μ΄μš©ν•΄ bar 객체, baz 객체 생성var bar = new Person('bar', 33, 'woman');console.dir(bar);
var baz = new Person('baz', 25, 'woman');console.dir(baz);

[좜λ ₯ κ²°κ³Ό]

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

❓ μ±…κ³Ό λ‹€λ₯Έ 좜λ ₯ κ²°κ³Ό

μ±…μ—μ„œλŠ” μƒμ„±μž ν•¨μˆ˜λ‘œ μƒμ„±λœ 객체 bar , baz 의 __proto__ : Person으둜좜λ ₯λ˜λŠ” κ²ƒμœΌλ‘œ λ‚˜μ˜΄


  • ν”„λ‘œν† νƒ€μž… 확인 κ²°κ³Ό
foo instanceof Person; // falsePerson.prototype.isPrototypeOf(foo); // falseObject.prototype.isPrototypeOf(foo); // true
bar instanceof Person; // truePerson.prototype.isPrototypeOf(bar); // trueObject.prototype.isPrototypeOf(bar); // true
baz instanceof Person; // truePerson.prototype.isPrototypeOf(baz); // trueObject.prototype.isPrototypeOf(baz); // true

⭐ μƒμ„±μž ν•¨μˆ˜λ₯Ό new λ₯Ό 뢙이지 μ•Šκ³  ν˜ΈμΆœν•  경우

객체 생성을 λͺ©μ μœΌλ‘œ μž‘μ„±ν•œ μƒμ„±μž ν•¨μˆ˜λ₯Ό new λ₯Ό 뢙이지 μ•Šκ±°λ‚˜, 일반 ν•¨μˆ˜λ₯Ό new λ₯Ό λΆ™μ—¬ ν˜ΈμΆœν•  경우 였λ₯˜κ°€ λ°œμƒν•  수 μžˆλ‹€. ( this 바인딩 방식이 λ‹€λ₯΄κΈ°λ•Œλ¬Έ)

function Person(name, age, gender, position) {    this.name = name;    this.age = age;    this.gender = gender;}
var qux = Person('qux', 20, 'man');console.log(qux); // undefined
console.log(window.name); // quxconsole.log(window.age); // 20console.log(window.gender); // man

μƒμ„±μž ν•¨μˆ˜ Person( ... ) 에 return 이 μ—†κΈ° λ•Œλ¬Έμ— qux λŠ” undefined κ°€μΆœλ ₯λœλ‹€.

μƒμ„±μž ν•¨μˆ˜λ₯Ό new ν‚€μ›Œλ“œμ—†μ΄ 일반 ν•¨μˆ˜ ν˜•νƒœλ‘œ ν˜ΈμΆœν–ˆκΈ° λ•Œλ¬Έμ— this κ°€ 전역객체인 window 객체둜 바인딩 λœλ‹€.

μ΄λŸ¬ν•œ 였λ₯˜λ₯Ό λ°©μ§€ν•˜κΈ° μœ„ν•΄ 일반적으둜 μƒμ„±μž ν•¨μˆ˜λ‘œ μ‚¬μš©ν•  ν•¨μˆ˜λŠ” 첫 κΈ€μžλ₯Ό λŒ€λ¬Έμžλ‘œ ν‘œκΈ°ν•œλ‹€. λ˜ν•œ μΆ”κ°€μ μœΌλ‘œ λ‹€μŒμ˜ νŒ¨ν„΄μ„ μ‚¬μš©ν•˜λŠ” 것도 κ°€λŠ₯ν•˜λ‹€.

function A(arg) {    if (!(this instanceof A)) return new A(arg);    this.value = arg ? arg : 0;}var a = new A(100);var b = A(10);
console.log(a.value); // 100console.log(b.value); // 10console.log(global.value); // undefined

ν•¨μˆ˜ Aκ°€ 호좜될 λ•Œ this κ°€ A의 μΈμŠ€ν„΄μŠ€κ°€ μ•„λ‹ˆλΌλ©΄ new 둜 호좜된 것이 μ•„λ‹˜μ„μ˜λ―Έν•˜κ³  이 경우 new 둜 Aλ₯Ό ν˜ΈμΆœν•˜μ—¬ λ°˜ν™˜ν•˜κ²Œ ν•˜μ˜€λ‹€.

μ–΄λ–€ μ½”λ“œμ—μ„œλŠ” if (!(this instanceof arguments.callee)) 둜 μž‘μ„±ν•¨μœΌλ‘œ, νŠΉμ •ν•¨μˆ˜ 이름과 상관없이 이 νŒ¨ν„΄μ„ μ‚¬μš©ν•˜λ„λ‘ ν•œλ‹€.


call κ³Ό apply λ©”μ†Œλ“œλ₯Ό μ΄μš©ν•œ λͺ…μ‹œμ μΈ this 바인딩#

각각의 상황에 따라 this κ°€ μžλ™μœΌλ‘œ λ°”μΈλ”©λ˜λŠ”λ°, μ΄λŸ¬ν•œ 내뢀적인 this 바인딩 이외에도 this λ₯Ό νŠΉμ • 객체에 λͺ…μ‹œμ μœΌλ‘œ λ°”μΈλ”©μ‹œν‚€λŠ” 방법도 μžˆλ‹€. apply() 와 call() λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•¨μœΌλ‘œ κ°€λŠ₯ν•˜λ‹€.

이 λ©”μ†Œλ“œλ“€μ€ λͺ¨λ“  ν•¨μˆ˜μ˜ λΆ€λͺ¨ 객체인 Function.prototype 객체의 λ©”μ†Œλ“œμ΄λ―€λ‘œ, λͺ¨λ“  ν•¨μˆ˜λŠ” λ‹€μŒκ³Ό 같은 ν˜•μ‹μœΌλ‘œ apply() λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•˜λŠ” 것이 κ°€λŠ₯ν•˜λ‹€.

function.apply(thisArg, argArray)

call() λ©”μ†Œλ“œλŠ” apply() λ©”μ†Œλ“œμ™€ κΈ°λŠ₯이 κ°™κ³  단지 λ„˜κ²¨λ°›λŠ” 인자의 ν˜•μ‹λ§Œ λ‹€λ₯΄λ‹€.

μš°μ„  apply() λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•˜λŠ” 주체가 ν•¨μˆ˜κ³ , apply() λ©”μ†Œλ“œλ„ this λ₯Ό νŠΉμ • 객체에 바인딩할 뿐 본질적인 κΈ°λŠ₯은 ν•¨μˆ˜ ν˜ΈμΆœμ΄λΌλŠ” 것이닀.

첫 번째 인자 thisArg λŠ” apply() λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•œ ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ μ‚¬μš©ν•œ this 에 바인딩할 객체λ₯Ό 가리킨닀. 두 번째 argArray μΈμžλŠ” ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•Œ λ„˜κΈΈ μΈμžλ“€μ˜ 배열을 가리킨닀.

// μƒμ„±μž ν•¨μˆ˜function Person(name, age, gender) {    this.name = name;    this.age = age;    this.gender = gender;}
// foo 빈 객체 생성var foo = {};
// apply() λ©”μ†Œλ“œ 호좜Person.apply(foo, ['foo', 30, 'man']);console.dir(foo);

[좜λ ₯ κ²°κ³Ό]

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

첫 번째 인자둜 λ„˜κΈ΄ foo κ°€ Person() ν•¨μˆ˜μ—μ„œ this λ°”μΈλ”©λœλ‹€. apply() λ©”μ†Œλ“œμ˜ 두 번째 인자둜 λ„˜κΈ΄ λ°°μ—΄ ['foo', 30, 'man']은 ν˜ΈμΆœν•˜λ €λŠ” Person() ν•¨μˆ˜μ˜ 인자 name , age , gender 둜 각각 μ „λ‹¬λœλ‹€.

call() λ©”μ†Œλ“œλŠ” apply() 와 κΈ°λŠ₯이 κ°™μ§€λ§Œ apply() 의 두 번째 μΈμžμ—μ„œ λ°°μ—΄ν˜•νƒœλ‘œ λ„˜κΈ΄ 것을 각각 ν•˜λ‚˜μ˜ 인자둜 λ„˜κΈ΄λ‹€.

Person.call(foo, 'foo', 30, 'man');

apply() 와 call() λ©”μ†Œλ“œμ˜ λŒ€ν‘œμ μΈ μš©λ„κ°€ arguments 객체와 같은 μœ μ‚¬ λ°°μ—΄ κ°μ²΄μ—μ„œ λ°°μ—΄ λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•˜λŠ” κ²½μš°μ΄λ‹€.

function myFunction() {    var args = Array.prototype.slice.apply(arguments);    console.dir(args);}
myFunction(1, 2, 3);

이 μ½”λ“œλŠ” μ΄λ ‡κ²Œ 해석될 수 μžˆλ‹€.

Array.prototype.slice() λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•΄λΌ. 이 λ•Œ this λŠ” arguments 객체둜 바인딩해라.


ν•¨μˆ˜ 리턴#

μžλ°”μŠ€ν¬λ¦½νŠΈ ν•¨μˆ˜λŠ” 항상 리턴값을 λ°˜ν™˜ν•œλ‹€. 특히 return 문을 μ‚¬μš©ν•˜μ§€ μ•Šμ•˜λ”λΌλ„ 항상 λ‹€μŒμ˜ κ·œμΉ™μœΌλ‘œ 리턴값을 μ „λ‹¬ν•˜κ²Œλœλ‹€.

κ·œμΉ™ 1) 일반 ν•¨μˆ˜λ‚˜ λ©”μ†Œλ“œλŠ” 리턴값을 μ§€μ •ν•˜μ§€ μ•Šμ„ 경우 undefined κ°€ λ¦¬ν„΄λœλ‹€#

// noReturnFunc() ν•¨μˆ˜var noReturnFunc = function () {    console.log(β€˜This function has no return statement.’);};
var result = noReturnFunc(); // This function has no return statement.console.log(result); // undefined

κ·œμΉ™ 2) μƒμ„±μž ν•¨μˆ˜μ—μ„œ 리턴값을 μ§€μ •ν•˜μ§€ μ•Šμ„ 경우 μƒμ„±λœ 객체가 λ¦¬ν„΄λœλ‹€#

μƒμ„±μž ν•¨μˆ˜μ—μ„œλŠ” 일반적으둜 리턴값을 μ§€μ •ν•˜μ§€ μ•Šκ³ , μƒˆλ‘œ μƒμ„±λœ 객체가 λ¦¬ν„΄λ˜λ„λ‘ ν•œλ‹€. 그런데 λ§Œμ•½ this 둜 λ°”μΈλ”©λ˜λŠ” μƒμ„±λœ 객체가 μ•„λ‹Œ λ‹€λ₯Έ 객체λ₯Ό λ¦¬ν„΄ν•˜λ©΄ μ–΄λ–»κ²Œ 될 것인가?

// Person() μƒμ„±μž ν•¨μˆ˜function Person(name, age, gender) {    this.name = name;    this.age = age;    this.gender = gender;
    // λͺ…μ‹œμ μœΌλ‘œ λ‹€λ₯Έ 객체 λ°˜ν™˜    return {name: 'bar', age: 20, gender: 'woman'};}
var foo = new Person('foo', 30, 'man');console.dir(foo);

[좜λ ₯ κ²°κ³Ό]

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

좜λ ₯ κ²°κ³Όλ₯Ό μ‚΄νŽ΄λ³΄λ©΄, μƒμ„±μž ν•¨μˆ˜μ˜ 리턴값을 객체 λ¦¬ν„°λŸ΄ λ°©μ‹μ˜ νŠΉμ • 객체둜 μ§€μ •ν•œ 경우 new μ—°μ‚°μžλ‘œ Person() ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•΄μ„œ μƒˆλ‘œμš΄ 객체λ₯Ό μƒμ„±ν•˜λ”λΌλ„ λ¦¬ν„΄κ°’μ—μ„œ λͺ…μ‹œμ μœΌλ‘œ λ„˜κΈ΄ κ°μ²΄λ‚˜ 배열이 λ¦¬ν„΄λœλ‹€.

ν•˜μ§€λ§Œ μƒμ„±μž ν•¨μˆ˜μ˜ λ¦¬ν„΄κ°’μœΌλ‘œ λ„˜κΈ΄ 값이 객체가 μ•„λ‹Œ λ¬Έμžμ—΄, 숫자, Boolean이라면 μ΄λŸ¬ν•œ 리턴값을 λ¬΄μ‹œν•˜κ³  this 둜 λ°”μΈλ”©λœ 객체가 λ¦¬ν„΄λœλ‹€.

function Person(name, age, gender) {    this.name = name;    this.age = age;    this.gender = gender;
    return 100;}
var foo = new Person('foo', 30, 'man');console.log(foo); // Person { name: 'foo', age: 30, gender: 'man' }

참고자료#