본문 바로가기
항해99

[항해99 1주차] JS문법 종합반 - 3주차

by 지 요니 2023. 4. 7.

 

데이터 타입 심화

  • 데이터 타입의 종류

더보기

💡 [기본형과 참조형의 구분 기준] => 값의 저장방식, 불변성 여부

  1. 복제의 방식
    1. 기본형 : 값이 담긴 주소값을 바로 복제
    2. 참조형 : 값이 담긴 주소값들로 이루어진 묶음을 가리키는 주소값을 복제
  2. 불변성의 여부
    1. 기본형 : 불변성을 띔
    2. 참조형 : 불변성을 띄지 않음
  • 메모리와 데이터

- 비트

  1. 컴퓨터가 이해할 수 있는 가장 작은 단위
  2. 0과 1을 가지고 있는 메모리를 구성하기 위한 작은 조각

- 바이트

- 메모리 : byte 단위로 구성

  1. 모든 데이터는 byte 단위의 식별자인 메모리 주소값으로 서로 구분
  2. 만일, 64비트(8바이트) 정수는 메모리에 어떻게 저장? => 64비트를 8개의 바이트로 분할하고, 각 바이트를 메모리에 저장, 따라서 64비트 정수는 메모리에서 8개의 연속된 바이트에 저장

- java, c와 다른 javascript의 메모리 관리 방식(feat. 정수형)

  • 8을 저장하는 방법
  1. JS : let a = 8(8byte)
  2. JAVA
    1. byte a = 8(1byte)
    2. short a = 8(2byte)
    3. int a = 8(4byte)
    4. long a = 8(16byte)

- 식별자, 변수

더보기

var testValue = 3

변수 = 데이터

식별자 = 변수명

  • 변수 선언과 데이터 할당

- 할당 예시

/** 선언과 할당을 풀어 쓴 방식 */
var str;
str = 'test!';

/** 선언과 할당을 붙여 쓴 방식 */
var str = 'test!';

- 값을 바로 변수에 대입하지 않는 이유

  1. 자유로운 데이터 변환
    1. 이미 입력한 문자열이 길어진다면?
    2. 숫자는 항상 8byte로 고정이지만, 문자는 고정x(영문 : 1byte, 한글 : 2byte). 그래서, 이미 주소에 할당된 데이터를 변환하려 할 때 훨씬 더 큰 데이터를 저장하려 한다면 →  이후부터 저장되어있는 모든 데이터를 다 미뤄야함.
  2. 메모리의 효율적 관리
    1. 똑같은 데이터를 여러번 저장해야 한다면?
    2. 1만개의 변수를 생성해서 모든 변수에 숫자 1을 할당하는 상황을 가정
    3. 모든 변수를 별개로 인식한다고 한다면, 1만개의 변수 공간을 확보
      1. 바로 대입하는 case) 숫자형은 8 바이트 고정이죠
        1. 1만개 * 8byte = 8만 byte
      2. 변수 영역에 별도 저장 case)
        1. 변수 영역 : 2바이트 1만개 = 2만바이트 (변수 영역에 저장되는 데이터는 2바이트로 가정)
        2.  
        3. 데이터 영역 : 8바이트 1개 = 8바이트
        4. 총 : 2만 8바이트

- 기본형 데이터와 참조형 데이터

  • 변수 vs 상수
    • 변수: 변수 영역 메모리 변경 o
    • 상수: 변수 영역 메모리 변경 x
  • 불변 vs 불변x
    • 불변: 데이터 영역 메모리 변경 x
    • 불변x : 데이터 영역 메모리 변경 o

가변값과 가변성(참조형 데이터)

  • 참조형 데이터의 변수 할당 과정
// 참조형 데이터는 별도 저장공간(obj1을 위한 별도 공간)이 필요합니다!
var obj1 = {
	a: 1,
	b: 'bbb,
};

 

 

 

실행컨텍스트(스코프, 변수, 객체, 호이스팅)

  • 실행 컨텍스트: 실행할 코드에 제공할 환경 정보들을 모아놓은 객체

- 스택 vs 큐

- 콜 스택(call stack)

: 실행 컨텍스트 즉, 동일 환경에 있는 코드를 실행할 때 필요한 환경 정보들을 모아 놓은 객체를 '스택'의 한 종류인 콜스택에 쌓아 올림. 가장 위에 쌓여있는 컨텍스트와 관련된 코드를 실행하는 방법으로 코드의 환경 및 순서를 보장

  1. 컨텍스트의 구성
    1. 구성방법
      • 전역공간
      • eval()함수
      • 함수(우리가 흔히 실행컨텍스트를 구성하는 방법)
    2. 실행컨텍스트 구성 예시 코드
      // ---- 1번
      var a = 1;
      function outer() {
      	function inner() {
      		console.log(a); //undefined
      		var a = 3;
      	}
      	inner(); // ---- 2번
      	console.log(a);
      }
      outer(); // ---- 3번
      console.log(a);
      
    3. 실행컨텍스트 구성 순서
      코드실행 → 전역(in) → 전역(중단) + outer(in) → outer(중단) + inner(in) → inner(out) + outer(재개) → outer(out) + 전역(재개) → 전역(out) → 코드종료
    4. 특정 실행 컨텍스트가 생성되는(또는 활성화되는) 시점이 콜 스택의 맨 위에 쌓이는(노출되는) 순간을 의미
      곧, 현재 실행할 코드에 해당 실행 컨텍스트가 관여하게 되는 시점을 의미

- 실행 컨텍스트 객체의 실체(=담기는 정보)

  1. VariableEnvironment
    1. 현재 컨텍스트 내의 식별자 정보(=record)를 가짐
      1. var a = 3
      2. 위의 경우, var a를 의미
    2. 외부 환경 정보(=outer)를 가짐
    3. 선언 시점 LexicalEnvironment의 snapshot
  2. LexicalEnvironment
    1. VariableEnvironment와 동일하지만, 변경사항을 실시간으로 반영
  3. ThisBinding
    1. this 식별자가 바라봐야할 객체
  • VariableEnvironment, LexicalEnvironment의 개요

- VE vs LE => 담기는 항목 동일

  1. VE : 스냅샷을 유지
  2. LE : 스냅샷을 유지x  즉, 실시간으로 변경사항을 계속해서 반영

=> 실행 컨텍스트 생성할 때, VE에 정보 먼저 담고, 복사하여 LE를 생성, 그 이후 LE활용

- 구성요소(VE, LE 동일)

  1. environmentRecord(=record)
    1. 현재 컨텍스트와 관련된 코드의 식별자 정보들이 저장
    2. 함수에 지정된 매개변수 식별자, 함수자체, var로 선언된 변수 식별자 등
  2. outerEnvironmentReference(=outer)
  • LexicalEnvironment - environmentRecord(=record)와 호이스팅

- 개요

  1. 현재 컨텍스트와 관련된 코드의 식별자 정보들이 저장(수집)
  2. 수집 대상 정보 : 함수에 지정된 매개변수 식별자, 함수 자체, var로 선언된 변수 식별자 등
  3. 컨텍스트 내부를 처음부터 끝까지 순서대로 훑어가며 수집

- 호이스팅 => record 수집 과정

  1. 변수정보 수집을 모두 마쳤더라도 아직 실행 컨텍스트가 관여할 코드는 실행 전의 상태(JS 엔진은 코드 실행 전 이미 모든 변수정보를 알고 있는 것)
  2. 변수 정보 수집 과정을 이해하기 쉽게 설명한 ‘가상 개념’

- 호이스팅 규칙

더보기
  • 호이스팅 법칙 1 : 매개변수 및 변수는 선언부를 호이스팅 

<적용 전>

//action point 1 : 매개변수 다시 쓰기(JS 엔진은 똑같이 이해한다)
//action point 2 : 결과 예상하기
//action point 3 : hoisting 적용해본 후 결과를 다시 예상해보기

function a (x) {
	console.log(x);
	var x;
	console.log(x);
	var x = 2;
	console.log(x);
}
a(1);

<매개변수 적용>

//action point 1 : 매개변수 다시 쓰기(JS 엔진은 똑같이 이해한다)
//action point 2 : 결과 예상하기
//action point 3 : hoisting 적용해본 후 결과를 다시 예상해보기

function a () {
	var x = 1;
	console.log(x);
	var x;
	console.log(x);
	var x = 2;
	console.log(x);
}
a(1);

<호이스팅 적용>

//action point 1 : 매개변수 다시 쓰기(JS 엔진은 똑같이 이해한다)
//action point 2 : 결과 예상하기
//action point 3 : hoisting 적용해본 후 결과를 다시 예상해보기

function a () {
	var x;
	var x;
	var x;

	x = 1;
	console.log(x);
	console.log(x);
	x = 2;
	console.log(x);
}
a(1);
  • 예상: 1 → undined → 2
  • 실제: 1 → 1 → 2
더보기
  • 호이스팅 법칙 2 : 함수 선언은 전체를 호이스팅

<적용 전>

//action point 1 : 결과 값 예상해보기
//action point 2 : hoisting 적용해본 후 결과를 다시 예상해보기

function a () {
	console.log(b);
	var b = 'bbb';
	console.log(b);
	function b() { }
	console.log(b);
}
a();

<호이스팅 적용>

//action point 1 : 결과 값 예상해보기
//action point 2 : hoisting 적용해본 후 결과를 다시 예상해보기

function a () {
	var b; // 변수 선언부 호이스팅
	function b() { } // 함수 선언은 전체를 호이스팅

	console.log(b);
	b = 'bbb'; // 변수의 할당부는 원래 자리에

	console.log(b);
	console.log(b);
}
a();
  • 예상: 에러(또는 undefined) → ‘bbb’ → b함수
  • 실제: b함수 → ‘bbb’ → ‘bbb’

* 주의할 점

- 함수 정의 방식 => 함수 표현식을 활용하는 습관을 들이자!

함수 선언문을 이용한 코드는 함수 전체가 위로 올라오고,

함수 표현식을 이용한 코드는 함수 선언부만 위로 올라오므로 그 이후의 코드만 영향 받음!

// 함수 선언문. 함수명 a가 곧 변수명
// function 정의부만 존재, 할당 명령이 없는 경우
function a () { /* ... */ }
a(); // 실행 ok

// 함수 표현식. 정의한 function을 별도 변수에 할당하는 경우
// (1) 익명함수표현식 : 변수명 b가 곧 변수명(일반적 case에요)
var b = function () { /* ... */ }
b(); // 실행 ok

// (2) 기명 함수 표현식 : 변수명은 c, 함수명은 d
// d()는 c() 안에서 재귀적으로 호출될 때만 사용 가능하므로 사용성에 대한 의문
var c = function d () { /* ... */ } 
c(); // 실행 ok
d(); // 에러!

<호이스팅 적용>

// 함수 선언문은 전체를 hoisting
function sum (a, b) { // 함수 선언문 sum
	return a + b;
}

// 변수는 선언부만 hoisting

var multiply; 

console.log(sum(1, 2));
console.log(multiply(3, 4));

multiply = function (a, b) { // 변수의 할당부는 원래 자리
	return a + b;
};
  • LexicalEnvironment - 스코프, 스코프 체인, outerEnvironmentReference(=outer)

- 주요 용어

  1. 스코프
    1. 식별자에 대한 유효범위를 의미해요
    2. 대부분 언어에서 존재하구요, 당연하게도 JS에서도 존재하죠
  2. 스코프 체인
    1. 식별자의 유효범위를 안에서부터 바깥으로 차례로 검색해나가는 것

3. outerEnvironmentReference(이하 outer) : 스코프 체인이 가능토록 하는 것(외부 환경의 참조정보)

- 스코프 체인

  1. outer는 현재 호출된 함수가 선언될 당시의 LexicalEnvironment를 참조(그 당시의 환경 정보를 저장)
  2. 예를 들어, A함수 내부에 B함수 선언 → B함수 내부에 C함수 선언(Linked List)한 경우
  3. 결국 타고, 타고 올라가다 보면 전역 컨텍스트의 LexicalEnvironment를 참조하게 됩니다.
  4. 항상 outer는 오직 자신이 선언된 시점의 LexicalEnvironment를 참조하고 있으므로, 가장 가까운 요소부터 차례대로 접근 가능
  5. 결론 : 무조건 스코프 체인 상에서 가장 먼저 발견된 식별자에게만 접근이 가능
var a = 1;
var outer = function() {
	var inner = function() {
		console.log(a); //a=undefined => 호이스팅에 의해 var a, console.log(a), a=3이 됨
		var a = 3;
	};
	inner();
	console.log(a); // a=1 => inner는 이미 사라져서 참조x, 전역영역에서는 참조 가능
};
outer();
console.log(a); // a=1

각각의 실행 컨텍스트는 LE 안에 record와 outer를 가지고 있고, outer 안에는 그 실행 컨텍스트가 선언될 당시의 LE정보가 다 들어있으니 scope chain에 의해 상위 컨텍스트의 record를 읽어올 수 있다.

this(정의, 활용방법, 바인딩, call, apply, bind)

  • 상황에 따라 달라지는 this
  1. this는 실행 컨텍스트가 생성될 때 결정 => this는 함수를 호출할 때 결정
  • 전역 공간에서의 this
    1. 전역 공간에서 this는 전역 객체를 가리켜요.
    2. 런타임 환경에 따라 this는 window(브라우저 환경) 또는 global(node 환경)를 각각 가리킵니다.
더보기

런타임 환경: javascript로 만들어놓은 프로그램이 구동중인 환경

//브라우저 환경 this 확인
console.log(this);
console.log(window);
console.log(this === window);

//node 환경 this 확인
console.log(this);
console.log(global);
console.log(this === global);
  • 메서드로서 호출할 때 그 메서드 내부에서의 this
더보기

함수: 그 잧체로 독립적인 기능 수행 

함수명();

메서드: 자신을 호출한 대상 객체에 대한 동작 수행

객체.메서드명();

- this의 할당

// CASE1 : 함수
// 호출 주체를 명시할 수 없기 때문에 this는 전역 객체를 의미
var func = function (x) {
	console.log(this, x);
};
func(1); // Window { ... } 1

// CASE2 : 메서드
// 호출 주체를 명시할 수 있기 때문에 this는 해당 객체(obj)를 의미
// obj는 곧 { method: f }를 의미하죠?
var obj = {
	method: func,
};
obj.method(2); // { method: f } 2

- 함수로서의 호출과 메서드로서의 호출 구분 기준 : . []

- 메서드 내부에서의 this => this에는 호출을 누가 했는지에 대한 정보가 담김

var obj = {
	methodA: function () { console.log(this) },
	inner: {
		methodB: function() { console.log(this) },
	}
};

obj.methodA();             // this === obj
obj['methodA']();          // this === obj

obj.inner.methodB();       // this === obj.inner
obj.inner['methodB']();    // this === obj.inner
obj['inner'].methodB();    // this === obj.inner
obj['inner']['methodB'](); // this === obj.inner
  • 함수로서 호출할 때 그 함수 내부에서의 this

- 함수 내부에서의 this

  1. 어떤 함수를 함수로서 호출할 경우, this는 지정x(호출 주체가 알 수 x)
  2. 실행컨텍스트를 활성화할 당시 this가 지정되지 않은 경우, this는 전역 객체를 의미
  3. 따라서, 함수로서 ‘독립적으로’ 호출할 때this는 항상 전역객체를 가리킨다

- 메서드 내부함수의 this: 메서드의 내부라고 해도, 함수로서 호출한다면 this는 전역 객체를 의미

var obj1 = {
	outer: function() {
		console.log(this); // (1)
		var innerFunc = function() {
			console.log(this); // (2), (3)
		}
		innerFunc();

		var obj2 = {
			innerMethod: innerFunc
		};
		obj2.innerMethod();
	}
};
obj1.outer();
  • 실행결과: (1) : obj1, (2) : 전역객체, (3) : obj2

- 메서드의 내부 함수에서의 this 우회

  1. 변수를 활용하는 방법: 내부 스코프에 이미 존재하는 this를 별도의 변수(ex : self)에 할당하는 방법
var obj1 = {
	outer: function() {
		console.log(this); // (1) outer

		// AS-IS
		var innerFunc1 = function() {
			console.log(this); // (2) 전역객체
		}
		innerFunc1();

		// TO-BE
		var self = this;
		var innerFunc2 = function() {
			console.log(self); // (3) outer
		};
		innerFunc2();
	}
};

// 메서드 호출 부분
obj1.outer();

2. 화살표 함수(=this를 바인딩하지 않는 함수): 실행 컨텍스트를 생성할 때 this 바인딩 과정 자체가 없다!

더보기

일반 함수와 화살표 함수의 가장 큰 차이점은 무엇인가요? 

> this binding 여부가 가장 적절한 답

var obj = {
	outer: function() {
		console.log(this); // (1) obj
		var innerFunc = () => {
			console.log(this); // (2) obj
		};
		innerFunc();
	}
}

obj.outer();

- 콜백 함수 호출 시 그 함수 내부에서의 this

: 콜백 함수도 함수기 때문에 this는 전역 객체를 참조, 하지만 콜백함수를 넘겨받은 함수에서 콜백 함수에 별도로 this를 지정한 경우는 예외, 즉 콜백함수 내부의 this는 해당 콜백함수를 넘겨받은 함수(메서드)가 정한 규칙에 따라 값이 결정

// 별도 지정 없음 : 전역객체
setTimeout(function () { console.log(this) }, 300);

// 별도 지정 없음 : 전역객체
[1, 2, 3, 4, 5].forEach(function(x) {
	console.log(this, x);
});

// addListener 안에서의 this는 항상 호출한 주체의 element를 return하도록 설계되었음
// 따라서 this는 button을 의미함
document.body.innerHTML += '<button id="a">클릭</button>';
document.body.querySelector('#a').addEventListener('click', function(e) {
	console.log(this, e);
});
  1. setTimeout 함수, forEach 메서드는 콜백 함수를 호출할 때 대상이 될 this를 지정하지 않으므로, this는 곧 window객체
  2. addEventListner 메서드는 콜백 함수 호출 시, 자신의 this를 상속하므로, this는 addEventListner의 앞부분(button 태그)

- 생성자 함수 내부에서의 this

 

* 생성자 : 구체적인 인스턴스(어려우면 객체로 이해!)를 만들기 위한 일종의 틀

var Cat = function (name, age) {
	this.bark = '야옹';
	this.name = name;
	this.age = age;
};

var choco = new Cat('초코', 7); //this : choco
var nabi = new Cat('나비', 5);  //this : nabi
  • 명시적 this 바인딩 : 자동으로 부여되는 상황별 this의 규칙을 깨고 this에 별도의 값을 저장
  • call 메서드
    1. 호출 주체인 함수를 즉시 실행하는 명령어
    2. call명령어를 사용하여, 첫 번째 매개변수에 this로 binding할 객체를 넣어주면 명시적으로 binding할 수 o
var func = function (a, b, c) {
	console.log(this, a, b, c);
};

// no binding
func(1, 2, 3); // Window{ ... } 1 2 3

// 명시적 binding
// func 안에 this에는 {x: 1}이 binding돼요
func.call({ x: 1 }, 4, 5, 6}; // { x: 1 } 4 5 6

// 예상되는 this가 있음에도 일부러 바꾸는 연습
var obj = {
	a: 1,
	method: function (x, y) {
		console.log(this.a, x, y);
	}
};

obj.method(2, 3); // 1 2 3
obj.method.call({ a: 4 }, 5, 6); // 4 5 6
  • apply 메서드
    1. call 메서드와 완전히 동일! 다만, this에 binding할 객체는 똑같이 넣어주고 나머지 부분만 배열 형태로 넘겨줌.
var func = function (a, b, c) {
	console.log(this, a, b, c);
};
func.apply({ x: 1 }, [4, 5, 6]); // { x: 1 } 4 5 6

var obj = {
	a: 1,
	method: function (x, y) {
		console.log(this.a, x, y);
	}
};

obj.method.apply({ a: 4 }, [5, 6]); // 4 5 6
  • call / apply 메서드 활용

1. 유사배열객체(array-like-object)에 배열 메서드를 적용

더보기

유사배열의 조건

1. 반드시 length 필요

2. index번호가 0번부터 시작해서 1씩 증가

//객체에는 배열 메서드를 직접 적용할 수 없어요.
//유사배열객체에는 call 또는 apply 메서드를 이용해 배열 메서드를 차용할 수 있어요.
var obj = {
	0: 'a',
	1: 'b',
	2: 'c',
	length: 3
};
Array.prototype.push.call(obj, 'd');
console.log(obj); // { 0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4 }

var arr = Array.prototype.slice.call(obj);
console.log(arr); // [ 'a', 'b', 'c', 'd' ]

//slice(): 배열로 부터 특정 범위를 복사한 값들을 담고 있는 새로운 배열 만듦.
//첫번째 인자: 시작 인덱스, 두번째 인자: 종료 인덱스=> 시작 인덱스부터 종료 인덱스까지 값 복사

2. Array.from 메서드(ES6)

// 유사배열
var obj = {
	0: 'a',
	1: 'b',
	2: 'c',
	length: 3
};

// 객체 -> 배열
var arr = Array.from(obj);

// 찍어보면 배열이 출력됩니다.
console.log(arr);

3. 생성자 내부에서 다른 생성자를 호출(공통된 내용의 반복 제거)

function Person(name, gender) {
	this.name = name;
	this.gender = gender;
}
function Student(name, gender, school) {
	Person.call(this, name, gender); // 여기서 this는 student 인스턴스!
	this.school = school;
}
function Employee(name, gender, company) {
	Person.apply(this, [name, gender]); // 여기서 this는 employee 인스턴스!
	this.company = company;
}
var kd = new Student('길동', 'male', '서울대');
var ks = new Employee('길순', 'female', '삼성');

4. 여러 인수를 묶어 하나의 배열로 전달

//비효율
var numbers = [10, 20, 3, 16, 45];
var max = min = numbers[0];
numbers.forEach(function(number) {
	// 현재 돌아가는 숫자가 max값 보다 큰 경우
	if (number > max) {
		// max 값을 교체
		max = number;
	}

	// 현재 돌아가는 숫자가 min값 보다 작은 경우
	if (number < min) {
		// min 값을 교체
		min = number;
	}
});

console.log(max, min);

//효율
var numbers = [10, 20, 3, 16, 45];
var max = Math.max.apply(null, numbers);
var min = Math.min.apply(null, numbers);
console.log(max, min);

// 펼치기 연산자(Spread Operation)를 통하면 더 간편하게 해결도 가능해요
const numbers = [10, 20, 3, 16, 45];
const max = Math.max(...numbers);
const min = Math.min(...numbers);
console.log(max min);
  • bind 메서드:

: call과는 다르게 즉시 호출하지는 않고 넘겨받은 this 및 인수들을 바탕으로 새로운 함수를 반환하는 메서드

-  목적

  1. 함수에 this를 미리 적용!
  2. 부분 적용 함수 구현할 때 용이
var func = function (a, b, c, d) {
	console.log(this, a, b, c, d);
};
func(1, 2, 3, 4); // window객체

// 함수에 this 미리 적용
var bindFunc1 = func.bind({ x: 1 }); // 바로 호출되지는 않아요! 그 외에는 같아요.
bindFunc1(5, 6, 7, 8); // { x: 1 } 5 6 7 8

// 부분 적용 함수 구현
var bindFunc2 = func.bind({ x: 1 }, 4, 5); // 4와 5를 미리 적용
bindFunc2(6, 7); // { x: 1 } 4 5 6 7
bindFunc2(8, 9); // { x: 1 } 4 5 8 9

- name 프로퍼티:  bind 메서드를 적용해서 새로 만든 함수는 name 프로퍼티에 ‘bound’ 라는 접두어가 붙음(추적 용이)

var func = function (a, b, c, d) {
	console.log(this, a, b, c, d);
};
var bindFunc = func.bind({ x:1 }, 4, 5);

// func와 bindFunc의 name 프로퍼티의 차이를 살펴보세요!
console.log(func.name); // func
console.log(bindFunc.name); // bound func

- 상위 컨텍스트의 this를 내부함수나 콜백 함수에 전달하기

  1. 내부함수
    1. 메서드의 내부함수에서 메서드의 this를 그대로 사용하기 위한 방법
    2. self 등의 변수를 활용한 우회법보다 call, apply, bind를 사용하면 깔끔하게 처리 가능
var obj = {
	outer: function() {
		console.log(this); // obj
		var innerFunc = function () {
			console.log(this);
		};

		// call을 이용해서 즉시실행하면서 this를 넘겨주었습니다
		innerFunc.call(this); // obj
	}
};
obj.outer();

// bind()이용
var obj = {
	outer: function() {
		console.log(this);
		var innerFunc = function () {
			console.log(this);
		}.bind(this); // innerFunc에 this를 결합한 새로운 함수를 할당
		innerFunc();
	}
};
obj.outer();

2. 콜백함수

  1. 콜백함수도 함수이기 때문에, 함수가 인자로 전달될 때는 함수 자체로 전달(this 유실!)
  2. bind메서드를 이용해 this를 입맛에 맞게 변경 가능
var obj = {
	logThis: function () {
		console.log(this);
	},
	logThisLater1: function () {
		// 0.5초를 기다렸다가 출력해요. 정상동작하지 않아요.
		// 콜백함수도 함수이기 때문에 this를 bind해주지 않아서 잃어버렸어요!(유실)
		setTimeout(this.logThis, 500);
	},
	logThisLater2: function () {
		// 1초를 기다렸다가 출력해요. 정상동작해요.
		// 콜백함수에 this를 bind 해주었기 때문이죠.
		setTimeout(this.logThis.bind(this), 1000);
	}
};

obj.logThisLater1();
obj.logThisLater2();
  • 화살표 함수의 예외사항
  1. 화살표 함수는 실행 컨텍스트 생성 시, this를 바인딩하는 과정이 제외
  2. 이 함수 내부에는 this의 할당과정(바인딩 과정)이 아예 없으며, 접근코자 하면 스코프체인상 가장 가까운 this에 접근
  3. this우회, call, apply, bind보다 편리한 방법
var obj = {
	outer: function () {
		console.log(this);
		var innerFunc = () => {
			console.log(this);
		};
		innerFunc();
	};
};
obj.outer();

댓글