본 내용은 해당 강의 토대로 작성
1. this
VariablEnvironment | ||
---|---|---|
environmentRecord (snapshot) | ||
outerEnvironmentReference (snapshot) | ||
inner | LexicalEnvironment | |
environmentRecord | ||
outerEnvironmentReference | ||
ThisBinding | ||
outer | ||
전역 컨텍스트 |
- ThisBinding은 실행 컨텍스트가 활성화 될 때 일어난다.
- 함수가 호출 될 때 this가 결정된다.
호출하는 방식에 따른 ThisBinding
- 전역공간에서
- 함수 호출시
- 메소드 호출시
- callback 호출시
- 생성자함수 호출시
전역공간에서
- 처음부터 호출이 되어있으므로 정해져 있다.
- 전역객체를 가르킨다.
- 전역객체 : 개념상으로 전역 컨텍스트를 실행하는 주체
- window: 브라우저
- global: node.js
함수 호출시
- 함수는 전역객체의 메소드이다.(라고 생각하자)
- 전역객체를 가르킨다.
function a() {
console.log(this);
}
a();
- 함수를 실행하는 순간에 그것을 호출한 주체는 전역 공간이기 때문이다.(window)
function b(){
function c(){
console.log(this);
}
c();
}
b();
- 함수 c는 b내부에서 호출되지만, 역시 window를 가르킨다. (버그 추정)
var d = {
e: function() {
function f() {
console.log(this);
}
f(); /* 메소드 안에서 함수로서 호출 */
}
}
d.e();
- 함수 f는 메소드 안에서 호출되었지만, 함수로서 호출되었으므로 this는 전역객체를 가르킨다.
메소드 호출시
- 메소드 호출 주체 (메소드명 앞)
var a = {
b: function() {
console.log(this);
}
}
a.b(); /* a가 this */
------------------------------------------------------------------------------------
var a = {
b: {
c: function() {
console.log(this);
}
}
}
a.b.c(); /* a.b가 this */
내부함수에서의 우회법
- 내부함수에서 this를 호출했을 시, 전역객체를 가르키지 않게 할 수 있다.(메소드의 경우)
var a = 10;
var obj = {
a: 20,
b: function() {
console.log(this.a); /* 20 출력 */
function c() {
console.log(this.a); /* this가 window를 가르킴 */
}
c( ); /* 10 출력 */
}
}
obj.b();
- 함수 c는 메소드 내부에서 함수로서 호출되었다. 그러므로 함수 c로인해서 indow.a = 10이 출력된다.
var a = 10;
var obj = {
a: 20,
b: function() {
var self = this;
console.log(this.a);
function c() {
console.log(self.a);
}
c(); /* 20 출력 */
}
}
obj.b();
- this를 다른 변수에 담아, 내부에서 사용하면 위의 문제를 해결할 수 있다.
callback 호출시
- 기본적으로는 함수내부에서와 동일
- 제어권을 가진 함수가 callback의 this를 명시한 경우 그에 따른다.
- 개발자가 this를 바인딩한 채로 callback을 넘기 그에 따른다.
- 일반적인 경우 전역객체를 가르킨다.
var callback = function() {
console.dir(this); /* 전역객체 window */
};
var obj = {
a: 1,
b: function(cb) {
cb();
}
};
obj.b(callback);
- call 메소드로 this를 지정할 수 있다.
var callback = function() {
console.dir(this); /* obj */
};
var obj = {
a: 1,
b: function(cb) {
cb.call(this); /* this를 call 메소드로 지정 */
}
};
obj.b(callback);
- setTimeout
var callback = function() {
console.dir(this); /* window */
};
var obj = {
a: 1
};
setTimeout(callback, 100); /* 100secods 뒤에 callback 실행 */
- setTimeout에 bind를 사용하여 this를 지정할 수 있다.
var callback = function() {
console.dir(this); /* obj */
};
var obj = {
a: 1
};
setTimeout(callback.bind(obj), 100); /* this를 obj로 지정 */
- addEventListener
- 콜백함수 처리할 때, 그 대상 타겟으로 this를 정하게 되어있다.
document.body.innerHTML += '<div id = "a">클릭하세요</div>';
document.getElemetById('a')
.addEventListener('click', function() {
console.dir(this); /* div#a */
});
- bind로 this를 정의할 수 있다.
document.body.innerHTML += '<div id = "a">클릭하세요</div>';
var obj = { a: 1};
document.getElemetById('a')
.addEventListener('click', function() {
console.dir(this); /* obj */
}.bind(obj));
call, apply, bind 메소드에 대하여
- 명시적인 this 바인딩
func.call(thisArg[ , arg1[ , arg2[ , … ] ] ] )
func.apply(thisArg, [argsAraay])
func.bind(thisArg[. arg1[, arg2[, … ] ] ] )
- 대괄호는 생략 가능
- thisArg : this를 명시적을 지정
- call, apply : 즉시 호출
- bind : 새로운 함수 생성(currying)
function a(x, y, z) {
console.log(this, x, y, z);
}
var b = {
c: 'eee'
};
a.call(b, 1, 2, 3); /* Object {c: "eee"} 1 2 3 */
a.apply(b, [1, 2, 3]); /* Object {c: "eee"} 1 2 3 */
var c = a.bind(b);
c(1, 2, 3); /* Object {c: "eee"} 1 2 3 */
var d = a.bind(b, 1, 2);
d(3); /* Object {c: "eee"} 1 2 3 */
- a.call(b, 1, 2, 3): a를 호출하는데 ,this는 b, 인자는 1,2,3으로
- a.apply(b, [1, 2, 3]): a를 호출하는데, 괄호 안을 적용한다. this는 b로 인자는 배열로 실행한다.
- var c = a.bind(b): 새로운 함수 생성. this는 b
- var d = a.bind(b, 1, 2): 새로운 함수 생성, this는 b, 첫 번째 인자와 두 번째 인자는 1,2로 먼저 지정한다. 나머지 인자를 넣어서 호출할 수 있다.
생성자함수 호출시
- 인스턴스 자체가 this가 된다.
function Person(n, a) {
this.name = n; /* window */
this.age = a;
}
var gomugom = new Person('고무곰', 30); /* new로 인해 생성자 함수로 사용 */
console.log(gomugom); /* gomugom 객체 */
2. 콜백함수
- 호출해서 다시 돌려줄 함수
- 함수에 대한 제어권을 넘겨 준뒤 결과를 다시 돌려받는다.
제어권
실행 시점
- setIntercal: 주기마다 함수를 호출
setInterval( callback, milliseconds )
var cb = function() {
console.log('1초마다 실행될 겁니다.');
};
setInterval(cb, 1000);
- 함수의 제어권이 setInterval로 넘어간다.
인자
- .forEach : 배열의 값과 인덱스를 하나 하나씩 뽑아서 함수 실행
arr.forEach( callback [, thisArg])
var arr = [1, 2, 3, 4, 5];
var entries = [];
arr.forEach(function(v, i) { /* v : value i : index */
entries.push([i, v, this[i]]); /* forEach의 두 번째 인자가 this */
}, [10, 20, 30, 40, 50]);
console.log(entries);
/*
[[0, 1, 10], [1, 2, 20], [2, 3, 30], [3, 4, 40], [4, 5, 50]]
*/
this
- addEventListener
target.addEventListener( type, listener[, useCapture]);
- type: 등록할 event type을 나타내는 문자열
- listener: 특정 타입의 이벤트가 발생할 때 알림을 받을 객체. 수행하는 객체이거나, Javascript 함수 이어야 한다.( callback)
document.body.innerHTML = '<div id="a">abc</div>';
function cbFunc(x) {
console.log(this, x); /* 이벤트 대상이 this, x는 이벤트 객체 */
}
document.getElementById('a')
.addEventListener('Click', cbFunc);
$('#a').on('click', cbFunc);
콜백함수의 특징
- 다른 함수 (A)의 인자로 콜백함수(B)를 전달하면, A가 B의 제어권을 갖게 된다.
- 특별한 요청(bind)이 없는 한 A에 미리 정해놓은 방식에 따라 B를 호출한다.
- 미리 정해놓은 방식 : 어떤 시점에 콜백을 호출할지, 인자에는 어떤 값들을 지정할지, this에 무엇을 바인딩할지 등
주의
- 콜백은 '함수'이다.
var arr = [1, 2, 3, 4, 5];
var obj = {
vals: [1, 2, 3],
logValues: function(v, i) {
if(this.vals) { /* 메소드로 호출 시 */
cosole.log(this.vals, v, i);
} else {
console.log(this, v, i);
}
}
}
obj.logValues(1, 2); /* 메소드로 호출 */
arr.forEach(obj.logValues); /* callback함수로 전달 */
느낀점
this에서 신세계를 맛보았다.. 25분강의인데 이해하고 복습하는데 엄청 걸린 것 같다. 그래도, 이제 헷갈릴 일은 없을 것 같다!
'programming study > JavaScript' 카테고리의 다른 글
[프로그래머스] Hello, JavaScript: 자바스크립트 입문 (1) (2021.1.28) (0) | 2021.01.28 |
---|---|
[인프런 - 정재남] Javascript 핵심 개념 알아보기 - JS Flow (3)(2021.1.26) (0) | 2021.01.26 |
[인프런 - 정재남] Javascript 핵심 개념 알아보기 - JS Flow (1)(2021.1.22) (0) | 2021.01.22 |
[노마드코더]바닐라 JS로 크롬 앱 만들기 (5)(2021.1.20) (0) | 2021.01.20 |
[노마드코더]바닐라 JS로 크롬 앱 만들기 (4)(2021.1.19) (0) | 2021.01.19 |