양치기 공부스타일이 맞는 건지
처음 봤을 땐 하나도 이해 못 했던 내용들이
여러 강의랑 책이랑 번갈아가면서 공부하니까
제법 용어들도 눈에 익고 어느 정도 이해된다
(한.. 5%..? ㅎㅎ)
다음번에 볼 때는 이 내용들이 더 친근하게 와닿길..!
this는 기본적으로 실행 컨텍스트가 생성될 때 함께 결정되는데, 실행 컨텍스트는 함수를 호출할 때 생성된다. 즉, this는 함수를 호출할 때 결정된다. 함수를 어떤 방식으로 호출하느냐에 따라 값이 달라지는 것이다.
전역 공간에서의 this
전역 공간에서의 this는 객체를 가리킨다. 개념상 전역 컨텍스트를 생성하는 주체가 바로 전역 객체이기 때문이다. 전역 객체는 자바스크립트 런타임 환경에 따라 다른 이름과 정보를 가지고 있는데, 브라우저 환경에서 전역 객체는 window, Node.js환경에서는 global이다.
※ 전역 공간에서만 발생하는 특이한 성질 : 전역변수를 선언하면 자바스크립트 엔진은 이를 전역객체의 프로퍼티로도 할당한다. 변수이면서 객체의 프로퍼티이기도 한 셈.
var a = 1;
console.log(a); //1
console.log(window.a); //1
console.log(this.a); //1
자바스크립트의 모든 변수는 실은 특정 객체의 프로퍼티로서 동작한다. 사용자가 var 연산자를 이용해 변수를 선언하더라도 실제 자바스크립트 엔진은 어떤 특정 객체(L.E)의 프로퍼티로 인식하는 것이다.
※그렇다면 왜 a를 직접 호출할 때도 1이 나올까? 변수 a에 접근하고자 하면 스코프 체인에서 a를 검색하다가 가장 마지막에 도달하는 전역 스코프의 L.E 즉, 전역 객체에서 해당 프로퍼티 a를 발견해서 그 값을 반환하기 때문. 단순하게 (window.)이 생략된 것으로 봐도 무방함.
var a = 1;
delete window a; // false
console.log(a, window.a, this.a); // 1 1 1
window.c = 3;
delete window.c; // true
console.log(c, window.c, this.c) // uncaught ReferenceError : C is not defined
하지만 '삭제'의 경우, 전역변수 선언과 전역객체의 프로퍼티 할당은 전혀 다른데, 처음부터 전역객체의 프로퍼티로 할당한 경우에는 삭제가 되는 반면 전역변수로 선언한 경우에는 삭제가 되지 않는다.
메서드로서 호출할 때 그 메서드 내부에서의 this
함수 vs 메서드
함수를 실행하는 가장 일반적인 두 가지 방법은 함수로서 호출하는 경우와 메서드로서 호출하는 경우이다. 함수와 메서드는 미리 정의한 동작을 수행하는 코드 뭉치로 이 둘을 구분하는 유일한 차이는 독립성에 있다. 함수는 그 자체로 독립적인 기능을 수행하는 반면, 메서드는 자신을 호출한 대상 객체에 관한 동작을 수행한다.
어떤 함수를 객체의 프로퍼티에 할당한다고 해서 그 자체로서 무조건 메서드가 되는 것이 아니라 객체의 메서드로서 호출할 경우에만 메서드로서 동작하고, 그렇지 않으면 함수로 동작한다.
var func = function (x) {
console.log(this,x);
};
func(1); // window {...} 1
var obj = {
method: func
};
obj.method(2); // {method:f} 2
'함수로서 호출'과 '메서드로서 호출'을 어떻게 구분할까?
func(1) 앞에 점(.)이 없으니 함수로서 호출한 것이고, method 앞에 점이 있으니 메서드로서 호출한 것이다. 다시 말해 점 표기법이든 대괄호 표기법이든, 어떤 함수를 호출할 때 그 함수 이름(프로퍼티명) 앞에 객체가 명시돼 있는 경우에는 메서드, 그렇지 않은 모든 경우에는 함수로 호출한 것이다.
메서드 내부에서의 this
this에는 호출한 주체에 대한 정보가 담긴다. 어떤 함수를 메서드로서 호출하는 경우 호출 주체는 바로 함수명(프로퍼티명) 앞의 객체이다. 점 표기법의 경우 마지막 점 앞에 명시된 객체가 곧 this가 되는 것.
함수로서 호출할 때 그 함수 내부에서의 this
함수 내부에서의 this
어떤 함수를 함수로서 호출할 경우에는 this가 지정되지 않는다. this에는 호출한 주체에 대한 정보가 담기는데 함수로서 호출하는 것은 호출 주체(객체지향 언어에서의 객체)를 명시하지 않고 개발자가 코드에 직접 관여해서 실행한 것이기 때문에 호출 주체의 정보를 알 수 없는 것.
메서드 내부함수에서의 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)전역객체(Window), (3)obj2
this 바인딩에 관해서는 함수를 실행하는 당시의 주변 환경(메서드 내부인지, 함수 내부인지 등)은 중요하지 않고, 오직 해당 함수를 호출하는 구문 앞에 점 또는 대괄호 표기가 있는지 없는지가 관건인 것이다.
메서드 내부 함수에서의 this를 우회하는 방법
대표적인 우회 방법은 변수를 활용하는 것
var obj1 = {
outer: function () {
console.log(this); // (1) { outer:f }
var innerFunc1 = function () {
console.log(this); // (2) Window { ... }
}
innerFunc1();
var self = this;
var innerFunc2 = function() {
console.log(self); // (3) { outer:f }
};
innerFunc2();
}
};
obj1.outer();
this를 바인딩하지 않는 함수
ES6에서는 함수 내부에서 this가 전역객체를 바라보는 문제를 보완하고자 this를 바인딩하지 않는 화살표 함수arrow function를 새로 도입했다. 화살표 함수는 실행 컨텍스트를 생성할 때 this 바인딩 과정 자체가 빠지게 되어 상위 스코프의 this를 그대로 활용할 수 있다. 내부 함수를 화살표 함수로 바꾸면 '우회법'은 필요하지 않다. (ES5에서는 화살표 함수 사용 불가)
콜백 함수 호출 시 그 함수 내부에서의 this
함수 A의 제어권을 다른 함수(또는 메서드) B에게 넘겨주는 경우 함수 A를 콜백함수라 한다. 이때 함수 A는 함수 B의 내부 로직에 따라 실행되며, this 역시 함수 B내부 로직에서 정한 규칙에 따라 값이 결정된다. 콜백함수도 함수이기 때문에 기본적으로 this가 전역객체를 참조하지만, 제어권을 받은 함수에서 콜백 함수에 별도로 this가 될 대상을 지정한 경우에는 그 대상을 참조한다.
생성자 함수 내부에서의 this
생성자함수 : 어떤 공통된 성질을 지니는 객체들을 생성하는 데 사용하는 함수
객체지향 언어에서는 클래스Class, 클래스를 통해 만든 객체를 인스턴스instance 라고 한다.
(ex. 인간으로 예를 들면 직립 보행, 언어구사, 도구 사용 등의 공통 속성들을 모아 인간을 정의한 것이 바로 클래스이고, 각 사람들은 인간 클래스에 속한 인스턴스)
각 인스턴트들은 공통점도 있지만 저마다의 개성도 존재할 수 있다. 프로그래밍적으로 '생성자'는 구체적인 인스턴스를 만들기 위한 일종의 틀이다. 이 틀에는 해당 클래스의 공통 속성들이 미리 준비돼 있고, 여기에 구체적인 인스턴스의 개성을 더해 개별 인스턴스를 만들 수 있는 것.
자바스크립트는 함수에 생성자로서의 역할을 함께 부여했는데, new 명령어와 함께 함수를 호출하면 해당 함수가 생성자로서 동작하게 된다. 그리고 어떤 함수가 생성자 함수로서 호출된 경우 내부에서의 this는 곧 새로 만들 구체적인 인스턴트 자신이 된다.
생성자 함수를 호출하면 우선 생성자 prototype 프로퍼티를 참조하는 __Proto__라는 프로퍼티가 있는 객체(인스턴스)를 만들고, 미리 준비된 공통 속성 및 개성을 해당 객체(this)에 부여한다.
'개발공부 > JavaScript 책' 카테고리의 다른 글
코어 자바스크립트 #05 (콜백함수) (0) | 2021.12.07 |
---|---|
코어 자바스크립트 #04 (this - 2 명시적으로 this를 바인딩하는 방법) (0) | 2021.12.02 |
코어 자바스크립트 #02 (실행 컨텍스트, 호이스팅, 스코프 체인) (2) | 2021.11.16 |
코어 자바스크립트 #01 (데이터 타입) (0) | 2021.11.15 |
인사이드 자바스크립트 #10 (실행 컨텍스트와 스코프 체인) (0) | 2021.11.02 |