Chapter 05 - norux/javascript_study GitHub Wiki

5. μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ™€ ν΄λ‘œμ €

  • μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ(Execution Context)의 κ°œλ…
  • ν™œμ„± 객체(Activation Object)와 λ³€μˆ˜ 객체(Variable Object)
  • μŠ€μ½”ν”„ 체인(Scope Chain)
  • ν΄λ‘œμ €(Closure)

5.1 μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ κ°œλ…

  • Cμ–Έμ–΄μ˜ ν•¨μˆ˜ μ½œμŠ€νƒκ³Ό μœ μ‚¬ν•œ κ°œλ…
  • μ‹€ν–‰ κ°€λŠ₯ν•œ μ½”λ“œλ₯Ό ν˜•μƒν™”ν•˜κ³  κ΅¬λΆ„ν•˜λŠ” 좔상적인 κ°œλ… λ˜λŠ” μ‹€ν–‰ κ°€λŠ₯ν•œ μžλ°”μŠ€ν¬λ¦½νŠΈ μ½”λ“œ 블둝이 μ‹€ν–‰λ˜λŠ” ν™˜κ²½

μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ ν˜•μ„±λ˜λŠ” μ„Έκ°€μ§€ 경우

  1. μ „μ—­ μ½”λ“œ
  2. eval() ν•¨μˆ˜λ‘œ μ‹€ν–‰λ˜λŠ” μ½”λ“œ
  3. ν•¨μˆ˜μ•ˆμ˜ μ½”λ“œλ₯Ό μ‹€ν–‰ν•  경우

μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ μ •μ˜

ν˜„μž¬ μ‹€ν–‰λ˜λŠ” μ»¨ν…μŠ€νŠΈμ—μ„œ 이 μ»¨ν…μŠ€νŠΈμ™€ κ΄€λ ¨ μ—†λŠ” μ‹€ν–‰ μ½”λ“œκ°€ μ‹€ν–‰λ˜λ©΄, μƒˆλ‘œμš΄ μ»¨ν…μŠ€νŠΈκ°€ μƒμ„±λ˜μ–΄ μŠ€νƒμ— λ“€μ–΄κ°€κ³  μ œμ–΄κΆŒμ΄ κ·Έ μ»¨ν…μŠ€νŠΈλ‘œ μ΄λ™ν•œλ‹€.

console.log("Global Context");

function ExContext1() {
  console.log("EC1");
};

function ExContext2() {
  ExContext1();
  console.log("EC2");
};

ExContext2();

Question: μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ 생성과정(EC의 μŠ€νƒ) 그림으둜 그리기!!

5.2 μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ 생성 κ³Όμ •

  • ν™œμ„± 객체와 λ³€μˆ˜ 객체
  • μŠ€μ½”ν”„ 체인
function execute(param1, param2) {
  var a = 1, b = 2;

  function func() {
    return a + b;
  }

  return param1 + param2 + func();
}

execute(3, 4);

Question: μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλ₯Ό 그렀보자!!

5.2.1 ν™œμ„± 객체 생성

ν™œμ„± 객체: ECκ°€ μƒμ„±λ λ•Œ, ν•΄λ‹Ή μ»¨ν…μŠ€νŠΈμ—μ„œ 싀행에 ν•„μš”ν•œ μ—¬λŸ¬κ°€μ§€ 정보λ₯Ό 담은 객체

5.2.2 arguments 객체 생성

5.2.3 μŠ€μ½”ν”„ 정보 생성

[ [scope]] ν”„λ‘œνΌν‹°λ‘œ 참쑰되며, μŠ€μ½”ν”„ μ •λ³΄λŠ” 리슀트 ν˜•νƒœλ₯Ό 띄고 μžˆλ‹€.

5.2.4 λ³€μˆ˜ 생성

EC λ‚΄λΆ€μ—μ„œ μ‚¬μš©λ˜λŠ” μ§€μ—­λ³€μˆ˜κ°€ μƒμ„±λœλ‹€.

  • μ°Έκ³ : ν™œμ„±κ°μ²΄μ™€ λ³€μˆ˜κ°μ²΄λŠ” 같은 객체이닀.

λ³€μˆ˜μ˜ 생성과 μ΄ˆκΈ°ν™” λŠ” λΆ„λ¦¬λ˜μ–΄ 이루어진닀. μ—¬κΈ°μ„œλŠ” 생성 만 μ΄λ£¨μ–΄μ§€λ―€λ‘œ, μ§€μ—­ λ³€μˆ˜ a, bμ—λŠ” undefinedκ°€ ν• λ‹Ήλœλ‹€. func도 μƒμ„±λ§Œ λœλ‹€. μ΄ˆκΈ°ν™”λŠ” ν‘œν˜„μ‹μ΄ μ‹€ν–‰λ˜κΈ° μ „κΉŒμ§€λŠ” 이루어지지 μ•ŠλŠ”λ‹€.

5.2.5 this 바인딩

λ§ˆμ§€λ§‰ λ‹¨κ³„λ‘œ this 바인딩이 이루어진닀.

5.2.6 μ½”λ“œ μ‹€ν–‰

ECκ°€ μƒμ„±λ˜κ³  λ³€μˆ˜ 객체가 λ§Œλ“€μ–΄μ§„ 후에 μ½”λ“œμ— μžˆλŠ” ν‘œν˜„μ‹λ“€μ˜ 싀행이 이루어 μ§„λ‹€. 이 κ³Όμ •μ—μ„œ μ΄ˆκΈ°ν™” 과정이 μΌμ–΄λ‚œλ‹€.

  • μ°Έκ³ : μ „μ—­ ECλŠ” 일반 EC와 μ•½κ°„ λ‹€λ₯΄λ‹€. arguments 객체가 μ—†κ³ , 전역객체 ν•˜λ‚˜λ§Œμ„ ν¬ν•¨ν•˜λŠ” μŠ€μ½”ν”„ 체인이 μžˆλ‹€.

Node.jsμ—μ„œλŠ” μ΅œμƒμœ„ μ½”λ“œκ°€ μ „μ—­μ½”λ“œκ°€ μ•„λ‹ˆλ‹€.

//λΈŒλΌμš°μ € var a = 10; b = 15; console.log(window.a); //10 console.log(window.b); //15 // //Node.js var a = 10; b = 15; console.log(global.a); //undefined console.log(global.b); //15


## 5.3 μŠ€μ½”ν”„ 체인
Cμ–Έμ–΄λŠ” for, ifλ¬Έμ—μ„œμ˜ {} 블둝 μ—­μ‹œ μŠ€μ½”ν”„ μœ νš¨λ²”μœ„μ— λ“€μ–΄κ°€μ§€λ§Œ, μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” 였직 **ν•¨μˆ˜λ§Œ** μœ νš¨λ²”μœ„μ˜ λ‹¨μœ„κ°€ λœλ‹€.

[ [scope]] ν”„λ‘œνΌν‹°λ‘œ 각 ν•¨μˆ˜ κ°μ²΄λ‚΄μ—μ„œ μ—°κ²° 리슀트둜 κ΄€λ¦¬λ˜λ©°, 이λ₯Ό μŠ€μ½”ν”„ 체인이라 ν•œλ‹€.

|    | μŠ€μ½”ν”„ 체인 |
|:--:|:--------:|
| 3  | ....     |
| 2  | λ³€μˆ˜κ°μ²΄ 2 |
| 1  | λ³€μˆ˜κ°μ²΄ 1 |
| 0  | λ³€μˆ˜κ°μ²΄ 0 |
[μŠ€μ½”ν”„μ²΄μΈ 리슀트]

각 ν•¨μˆ˜λŠ” [ [scope]] ν”„λ‘œνΌν‹°λ‘œ μžμ‹ μ΄ μƒμ„±λœ EC의 μŠ€μ½”ν”„ 체인을 μ°Έμ‘°ν•œλ‹€.

### 5.3.1 μ „μ—­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ μŠ€μ½”ν”„ 체인
```javascript
var var1 = 1;
var var2 = 2;

Question: μ „μ—­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ κ·Έλ¦Ό 그렀보기

5.3.2 ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•œ 경우 μƒμ„±λ˜λŠ” μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ μŠ€μ½”ν”„ 체인

var var1 = 1;
var var2 = 2;
function func(){
  var var1 = 10;
  var var2 = 20;
}

func();

Question: μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ κ·Έλ¦Ό 그렀보기

μŠ€μ½”ν”„ 체인 정리

  • 각 ν•¨μˆ˜ κ°μ²΄λŠ” [ [scope]]ν”„λ‘œνΌν‹°λ‘œ ν˜„μž¬ μ»¨ν…μŠ€νŠΈμ˜ μŠ€μ½”ν”„ 체인을 μ°Έμ‘°ν•œλ‹€.
  • μƒˆλ‘œμš΄ ECκ°€ μƒμ„±λ˜λ©΄, ν˜„μž¬ μ‹€ν–‰λ˜λŠ” ν•¨μˆ˜ 객체의 [ [scope]]ν”„λ‘œνΌν‹°λ₯Ό λ³΅μ‚¬ν•˜κ³  μƒˆλ‘­κ²Œ μƒμ„±λœ λ³€μˆ˜κ°μ²΄λ₯Ό ν•΄λ‹Ή 체인 제일 μ•žμ— μΆ”κ°€ν•œλ‹€.
  • μŠ€μ½”ν”„ 체인 = ν˜„μž¬ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ λ³€μˆ˜κ°μ²΄ + μƒμœ„ μ»¨ν…μŠ€νŠΈμ˜ μŠ€μ½”ν”„ 체인
var value = 10;

function printValue() {
  return value;
}
function printFunc(func) {
  var value = 100;
  console.log(func());
}
printFunc(printValue);

Question: μœ„ ν•¨μˆ˜μ˜ κ²°κ³ΌλŠ” μ–΄λ–»κ²Œ 될까? μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ κ·Έλ¦Ό 그렀보기

hint. 각 ν•¨μˆ˜κ°€ 싀행될 λ•Œμ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ 무엇인지λ₯Ό 생각해야 ν•œλ‹€.

with ν‚€μ›Œλ“œ

μžλ°”μŠ€ν¬λ¦½νŠΈμ—λŠ” μŠ€μ½”ν”„μ²΄μΈμ„ μ‚¬μš©μžκ°€ μž„μ˜λ‘œ μˆ˜μ •ν•  수 μžˆλŠ” withλΌλŠ” ν‚€μ›Œλ“œκ°€ μžˆλ‹€.

withλŠ” evalκ³Ό ν•¨κ»˜, μ‚¬μš©ν•˜μ§€ 말아야 ν•  ν‚€μ›Œλ“œμ΄λ‹€. "Pure javascript evil.."

with ν‚€μ›Œλ“œλŠ” νŠΉμ • 객체λ₯Ό [ [scope]]리슀트 μ΅œμƒλ‹¨μ— μ˜¬λ¦¬λŠ” 역할을 ν•œλ‹€.

.

ν˜Έμ΄μŠ€νŒ…

ν•¨μˆ˜μ˜ 생성과정을 μ΄ν•΄ν–ˆλ‹€λ©΄, ν•¨μˆ˜μ˜ ν˜Έμ΄μŠ€νŒ…μ„ 이해할 수 μžˆμ„ 것이닀.

foo(); //TypeError bar(); //싀행됨 var foo = function() { ... } function bar() { ... } var x = 1;



## 5.4 ν΄λ‘œμ €

```javascript
function outerFunc(){
  var x = 10;
  var innerFunc() = function (){
    console.log(x);
  }
  return innerFunc;
}

var inner = outerFunc();
inner();   // 10

Question: 그림 그렀보기

inner()κ°€ 싀행될 λ•Œ, 이미 outerFunc의 μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλŠ” μ’…λ£Œλœ 후이닀. ν•˜μ§€λ§Œ, innerFunc의 μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ μŠ€μ½”ν”„μ²΄μΈμ—λŠ” outerFunc의 λ³€μˆ˜κ°μ²΄λŠ” λ‚¨μ•„μžˆκ²Œ λœλ‹€. 이것이 ν΄λ‘œμ €λΌλŠ” κ°œλ…μ΄λ‹€.

  • ν΄λ‘œμ €: 이미 생λͺ… μ£ΌκΈ°κ°€ λλ‚œ μ™ΈλΆ€ν•¨μˆ˜μ˜ λ³€μˆ˜λ₯Ό μ°Έμ‘°ν•˜λŠ” ν•¨μˆ˜
  • μžμœ λ³€μˆ˜: ν΄λ‘œμ €λ‘œ μ°Έμ‘°λ˜λŠ” μ™ΈλΆ€λ³€μˆ˜(즉, μœ„ μ˜ˆμ œμ—μ„œλŠ” x)
function outerFunc(arg1, arg2) {
  var local = 8;
  function innerFunc(innerArg){
    console.log((arg1 + arg2)/innerArg + local));
  }
  return innerFunc;
}
var exam1 = outerFunc(2, 4);
exam1(2);
}

Question: μœ„ κ²°κ³Ό μ˜ˆμΈ‘ν•΄λ³΄κΈ°

5.4.2 ν΄λ‘œμ €μ˜ ν™œμš©

μ„±λŠ₯, μžμ›μ μΈ λ©΄μ—μ„œ μ•½κ°„ 손해λ₯Ό λ³Ό 수 μžˆμœΌλ―€λ‘œ λ¬΄μ°¨λ³„μ μœΌλ‘œ μ‚¬μš©ν•΄μ„œλŠ” μ•ˆλœλ‹€.

ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°μ—μ„œ 많이 ν™œμš©λœλ‹€. 7μž₯μ—μ„œ μžμ„Έν•œ μ„€λͺ…을 ν•œλ‹€.

5.4.2.1 νŠΉμ • ν•¨μˆ˜μ— μ‚¬μš©μžκ°€ μ •μ˜ν•œ 객체의 λ©”μ„œλ“œ μ—°κ²°ν•˜κΈ°

function HelloFunc( func ) {
  this.greeting = "hello";
}

//HelloFunc μƒμ„±μž ν•¨μˆ˜μ— call λ©”μ„œλ“œ 동적 생성
HelloFunc.prototype.call = function( func ) {
  func ? func(this.greeting) : this.func(this.greeting);
}

function saySomething( obj, methodName, name ) {
  return ( function( greeting ) {
    return obj[methodName]( greeting, name );
  } );
}

// μƒμ„±μžν•¨μˆ˜ newObj()
function newObj( obj, name ) {
  obj.func = saySomething( this, "who", name );
  return obj;
}

// who λ©”μ„œλ“œ 동적 생성
newObj.prototype.who = function( greeting, name ) {
  console.log( greeting + " " + name || "everyone" ) );
}

var objHello = new HelloFunc();

var obj1 = new newObj( objHello, "zzoon" );
obj1.call();

//좜λ ₯κ²°κ³Ό
//hello zzoon

5.4.2.2 ν•¨μˆ˜μ˜ μΊ‘μŠν™”

I am XXX, I live in XXX, I'm XX years old

  • XXXμ—λŠ” μ‚¬μš©μžμ˜ μž…λ ₯을 λ°›μ•„ μœ„ λ¬Έμž₯을 λ§Œλ“€κΈ° μœ„ν•΄μ„œ, 배열을 μ΄μš©ν•˜μ—¬ λ§Œλ“€ 수 μžˆλ‹€.
var bufAry = [
  "I am ",
  "",
  ", I live in ",
  "",
  ", I'm ",
  "",
  " years old"
];
//이후 bufAry[1], bufAry[3], bufAry[5]에 μ‚¬μš©μžμ˜ 인풋을 λ„£μŒ

μœ„μ™€ 같은 μ½”λ“œλŠ” bufAryκ°€ μ „μ—­λ³€μˆ˜μ΄κΈ° λ•Œλ¬Έμ—, 외뢀에 λ…ΈμΆœλ˜μ–΄ μžˆλ‹€λŠ” 단점이 μžˆλ‹€. 이 μ½”λ“œλ₯Ό ν΄λ‘œμ €λ₯Ό ν™œμš©ν•˜μ—¬ λ°”κΎΈλ©΄ λ‹€μŒκ³Ό κ°™λ‹€.

var getCompletedString = ( function() {
  var bufAry = [
    "I am ",
    "",
    ", I live in ",
    "",
    ", I'm ",
    "",
    " years old"
  ];

  return ( function( name, city, age) {
    bufAry[1] = name;
    bufAry[3] = city;
    bufAry[5] = age;
  } );
} )();

var str = getCompletedString( "heebum", "seoul", 19 );

Question: μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ κ·Έλ¦Ό 그렀보기

5.4.2.3 setTimeout()에 μ§€μ •λ˜λŠ” ν•¨μˆ˜μ˜ μ‚¬μš©μž μ •μ˜

setTimeout()ν•¨μˆ˜: ν•¨μˆ˜λ₯Ό 인자둜 λ„˜κ²¨μ£Όμ–΄ μ‹€ν–‰ν•œλ‹€. ν•˜μ§€λ§Œ, ν•¨μˆ˜μ— 인자λ₯Ό ν•¨κ»˜ λ„˜κ²¨μ£Όμ§€λŠ” λͺ»ν•œλ‹€. 인자λ₯Ό λ„˜κ²¨μ£ΌκΈ° μœ„ν•΄ ν΄λ‘œμ € ν•¨μˆ˜λ₯Ό μ΄μš©ν•œλ‹€.

function callLater( obj, a, b) {
  return (function(){
    obj["sum"] = a + b;
  });

var sumObj = {
  sum : 0
}

var func = callLater( sumObj, 1, 2 );
setTimeout( func, 500);  //0.5초 ν›„ func() ν•¨μˆ˜ (ν΄λ‘œμ €) μ‹€ν–‰

5.4.3 ν΄λ‘œμ €λ₯Ό ν™œμš©ν•  λ•Œ, μ£Όμ˜μ‚¬ν•­

5.4.3.1 ν΄λ‘œμ €μ˜ ν”„λ‘œνΌν‹° 값은 μ“°κΈ° κ°€λŠ₯ν•˜λ―€λ‘œ, κ·Έ 값이 μ—¬λŸ¬λ²ˆ 호좜 될 λ•Œ 항상 λ³€ν• μˆ˜ μžˆμŒμ— μœ μ˜ν•΄μ•Ό ν•œλ‹€.

5.4.3.2 ν•˜λ‚˜μ˜ ν΄λ‘œμ €κ°€ μ—¬λŸ¬ ν•¨μˆ˜ 객체의 μŠ€μ½”ν”„ 체인에 λ“€μ–΄κ°€ μžˆλŠ” κ²½μš°λ„ μžˆλ‹€.

function func() {
  var x = 1;
  return {
    func1 : function(){ console.log( ++x ); }
    func2 : function(){ console.log( ~x ); }
  };
}

var exam = func();
exam.func1();
exam.func2();

5.4.3.3 루프 μ•ˆμ—μ„œ ν΄λ‘œμ €λ₯Ό ν™œμš©ν•  λ•ŒλŠ” μ£Όμ˜ν•˜λΌ

function countSeconds( howMany ) {
  for( var i = 1; i <= howMany; i++ ) {
    setTimeout( function() { console.log( i ); }, i * 1000 );
  }
}

countSeconds( 3 );

μœ„μ˜ μ˜ˆμ œλŠ” 1, 2, 3 을 1초 κ°„κ²©μœΌλ‘œ 좜λ ₯ν•˜λŠ” μ˜ˆμ œμ§€λ§Œ, 4, 4, 4 κ°€ 1초 κ°„κ²©μœΌλ‘œ 좜λ ₯λœλ‹€. setTimeout의 인자둜 λ“€μ–΄κ°€λŠ” 읡λͺ…ν•¨μˆ˜λŠ” μžμœ λ³€μˆ˜ iλ₯Ό μ°Έμ‘°ν•˜λŠ”λ°, 이 ν•¨μˆ˜κ°€ μ‹€ν–‰λ˜λŠ” μ‹œμ μ€ countSeconds() ν•¨μˆ˜μ˜ 싀행이 μ’…λ£Œλœ 이후 이기 λ•Œλ¬Έμ— μžμœ λ³€μˆ˜ iλŠ” 이미 4κ°€ 된 μƒνƒœμΈ 것이닀.

HB's Guess: 비동기 ν”„λ‘œκ·Έλž˜λ°μœΌλ‘œ μ‘μš© ν•  수 μžˆμ„ 것 κ°™μŒ