본문 바로가기
  • soldonii's devlog
Javascript 공부/코드스테이츠(-)

코드스테이츠 프리코스 5주차 후기(1)

by soldonii 2019. 8. 26.

*코드스테이츠 프리코스 33기를 수강하면서 2019년 5월 30일(목)에 학습한 내용을 정리한 포스팅입니다.

*https://soldonii.github.io에서 작성한 글을 티스토리로 옮겨온 포스팅입니다.

*자바스크립트를 배우는 단계라 오류가 있을 수 있습니다. 틀린 내용은 댓글로 말씀해주시면 수정하겠습니다. 감사합니다. :)


1. this

코드 스테이츠 Pre course 33기 5주차 목요일(2019-05-30)에는 ① this에 대해서 배웠다. this는 실행 컨텍스트 내에 담겨있는 식별자 중 하나이다. 따라서 this는 실행되는 시점이 중요하다!

 

1) 코드 실행 시, 자바스크립트 엔진에는 어떤 일이 발생할까?

let num 2;
function pow(num) {
  return num * num;
}

 

  • 변수와 함수가 전역 영역에서 생성됐으니, 전역 실행 컨텍스트(global execution context)가 아래 표처럼 생성이 되어 메모리에 저장된다.
  • 실행 컨텍스트는 block 단위에서는 생성되지 않고, function 단위로만 생성된다.
  • scope마다 이러한 실행 컨텍스트가 생긴다.

이러한 상황에서 function을 call하게 되면…

  • global scope에 local memory가 생성된다.
  • local execution context가 생성된다.

실행 context

  • 어떤 함수가 호출되면, 실행 컨텍스트(execution context)가 만들어진다.
    • call stack이라는 곳에 push되고, 함수를 벗어나면 call stack에서 pop된다.
  • scope별로 생성된다.
  • ① scope 내의 변수 및 함수(local, global), ② 전달인자(arguments), ③ 호출된 근원(caller), ④ this 등 총 4가지가 담겨 있다.

 

2) “this” keyword

  • 모든 함수 scope 내에서 자동으로 설정되는 특수한 식별자이다.
  • 실행 컨텍스트(execution context)의 구성요소 중 하나로, 함수가 실행되는 동안 이용할 수 있다.

 

3) this의 다섯가지 패턴

1. global : window

2. function 호출 : window. 함수가 여러 layer로 되어 있어도 window이다.

3. method 호출 : 부모 object. 객체가 여러 layer로 되어있을 경우 바로 하나 위의 부모 객체만 가져온다.

4. construction mode(new 연산자로 생성된 function 영역의this) : 새로 생성된 객체(즉, instance)

5. .call or .apply : call, apply의 첫번째 인자로 명시된 객체

 

1. global

// ① global scope에 선언된 변수, 함수에서의 this는 window
var name = 'Global Variables';
console.log(this.name); // "Global Variables"

function foo() {
  console.log(this.name); // "Global Variables"
}

 

2. function 호출

// ① 함수를 여러 layer로 중첩시켰을 때도, 함수 내에서 this는 window
// 함수를 생성하면 전역 객체인 window 객체 내의 속성으로 함수가 할당되기 때문에 그렇다.
var name = "Global Variables";

function outer() {
  function inner() {
    console.log(this.name); // "Global Variables";
  }
  inner();
}
outer();

// ② 마찬가지로 함수 내에서 호출된 this는 모두 window
var name = 'Global Variables';

function outer2() {
  var closure = function() {
    console.log(this.name); // "Global Variables"
  }
  return closure;
}
outer2()();

 

3. method 호출

// ① 객체 내의 value값으로 function을 주고(즉, method) 해당 method를 호출하면 this는 부모 객체를 지칭한다.
// 즉, 아래 사례의 경우 this는 counter이다.
var counter = {
  val : 0,
  increment : function() {
    this.val += 1;
  }
};

counter.increment();
console.log(couter.val); // 1
counter['increment']();
console.log(couter.val); // 2

// ② method가 실행되는 시점에서의 객체가 부모 객체이다.
var obj = {
  fn : function(a, b) {
    return this;
  }
};
var obj2 = {
  method : obj.fn
};

console.log(obj2.method() === obj2); // true
console.log(obj.fn() === obj); // true

 

  • 실행 컨텍스트이므로, 실행되는 시점에서의 부모가 누구인가를 찾는다.
  • console.log(obj2.method() === obj2)는 obj2에서 this가 실행되고 있으므로, 부모 객체는 obj2이다.
  • 쉽게 생각해서, ###.어쩌구() 이런 메소드 호출 시 ###에 들어가는 객체가 곧, 해당 method의 부모객체이자 this이다.

4. construction mode

function F(v) {
  this.val = v;
}
// create new instance of F
var f = new F('WooHoo!');

console.log(f.val); // "WooHoo!"
console.log(val); // ReferenceError
/* F라는 class의 새로운 instance f를 생성했다. 따라서 f 내에서 this를 호출할 경우 f를 지칭한다.
현재 함수 f는 아래와 같다.
  function f('WooHoo!') {this.val = 'WooHoo!';}
따라서 console.log(this.val) === console.log(f.val)이므로, "WooHoo!"가 출력된다.

 

 5. .call or .apply 호출

  • .call과 .apply는 함수를 호출하는 방식 중 하나이다.
function identify() {
  return this.name.toUpperCase();
}
function speak() {
  var greeting = "Hello, I'm " + identify.call(this);
  console.log(greeting);
}
var me = {name : "Kyle"};
var you = {name : "Reader"};

identify.call(me); // "KYLE"
identify.call(you); // "READER"
speak.call(me); // "Hello, I'm KYLE"
speak.call(you); // "Hello, I'm READER"

 

  • .call과 .apply는 괄호 안의 첫번째 인자로 객체를 받는데, 이 때 수신하는 객체가 바로 this이다.
  • 즉, identify.call(me)는 identify라는 함수를 호출하는데, me라는 객체를 인자로 받아서 호출하게 된다. 따라서 이 경우에서 this는 me가 되고, this.name.toUpperCase();라고 했으므로 결국 이는 me.name.toUpperCase();가 된다. 따라서 객체 me의 name의 value인 “Kyle”을 uppercase로 변환한 “KYLE”이 출력되는 것이다.
var add = function(x, y) {
  this.val = x + y;
}
var obj = {
  val : 0
};

add.apply(obj, [2, 8]); // this인 obj에 배열로 [2, 8]을 받았다. add 함수에 의해 2 + 8이 obj.val에 대입
console.log(obj.val); // 10
add.call(obj, 2, 8); // 마찬가지이지만 인자를 쉼표로 받았다.
console.log(obj.val); // 10

 

  • .call과 .apply는 인자를 수신받는 방식에 차이가 있다.
    • .call의 경우 parameter로 (객체, param1, param2, …) 이런 식으로 쉼표로 인자를 수신받고,
    • .apply의 경우 parameter로 (객체, [배열]) 이렇게 배열로 인자를 수신받는다.

댓글