참조형 데이터 타입, 실행 컨텍스트, this

김예린·2024년 1월 5일
0

가변값과 가변성

기본형 데이터의 변수 할당 과정과 차이점: 참조형 데이터는 별도의 저장공간이 필요하다.

참조형 데이터는 저장 객체 자체를 변경해주어야 혼란이 없다.

'얕은 복사'로 가변성에 대한 대처 가능!

//이런 패턴은 어떨까요?
var copyObject = function (target) {
	var result = {};

	// for ~ in 구문을 이용하여, 객체의 모든 프로퍼티에 접근할 수 있습니다.
	// 하드코딩을 하지 않아도 괜찮아요.
	// 이 copyObject로 복사를 한 다음, 복사를 완료한 객체의 프로퍼티를 변경하면
	// 되겠죠!?
	for (var prop in target) {
		result[prop] = target[prop];
	}
	return result;
}

빈 객체 result를 선언하고, 여기다가 객체를 순회하면서 복사한다. 복사를 한 객체의 prop를 변경하면 된다.
But, 이 방법은 depth=1인 객체만 복사할 수 있다. 예를 들어,

var user = {
	name: 'wonjang',
	urls: {
		portfolio: 'http://github.com/abc',
		blog: 'http://blog.com',
		facebook: 'http://facebook.com/abc',
	}
};

이런 식으로 중첩된 객체(깊이가 n)이면 못한다는 거.
이렇게 중첩된 객체는 재귀적 수행을 해야한다
재귀적 수행 -> 객체의 prop 중, 기본형 데이터는 그대로 복사 + 참조형 데이터는 다시 그 내부의 prop를 복사!

실행 컨텍스트

  • 실행할 코드에 제공할 변경정보를 모아놓은 객체

동일한 환경에 있는 코드를 싱행할 때 필요한 환경 정보들을 모아 컨텍스트를 구성하여 스택에 쌓아올린다.->콜스택
(stack은 FILO(first in, last out)이다)

실행컨텍스트 객체에 담기는 정보 1)VE 2)LE 3)this binding

1)VE(VariableEnvironment)

현재 컨텍스트내의 식별자 정보를 가지고 있다 ex)var a
외부 환경 정보(outer)를 가진다.
스냅샷을 유지한다.

2)LE(LexicalEnvironment)

ve와 동일하지만 스냅샷을 유지하지 않는다 = 실시간으로 변경사항을 반영한다.

스코프 체인: 식별자의 유효범위를 안에서부터 바깥으로 차례로 검색해나가는 것이다.
스코프 체인은 외부 환경의 참조를 가능하게 한다!
1. outer는 현재 호출된 함수가 선언될 당시의 LE를 참조
2. 항상 outer는 오직 자신이 선언된 시점의 LE를 참조하고 있으므로, 가장 가까운 요소부터 차례대로 접근 가능하다.
3. 그러니까 무조건 스코프 체인 상에서 가장 먼저 발견된 식별자에게만 접근 가능하다.

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

this binding

this는 실행 컨텍스트가 생성될때 결정된다 - 함수를 호출할때 결정된다.
1) 전역 공간에서의 this
전역 공간에서는 전역객체를 가리킴
node->global
browser->window
2) 메서드로서 호출할 때 그 메서드 내부에서의 this
함수명(); ->전역
객체.메소드명(); ->해당 객체

함수로서 독립적으로 호출할 때는 this는 항상 전역객체를 가리킨다.

화살표 함수(=this를 바인딩하지 않는 함수)

ES6문법에 첨 도입된 화살표 함수는 실행 컨텍스트를 생성할 때 this 바인딩 과정이 없다.

명시적 this binding

1)call

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

하드 코딩 느낌이라 잘 안씀.

2)apply

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과 거의 동일. this에 바인딩할 객체는 똑같이 해주고 나머지 부분만 배열 형태로[] 넘겨줌.

3)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

ㅋㅋㅋ잘 모르겠 ㄷ ㅏ

profile
아자아자

0개의 댓글