선요약
-함수는 다양한 환경에서 호출될 수 있다
-함수의 호출 환경에 따라 this는 동적으로 세팅된다(dynamic binding)
-bind, apply, call 등으로 this가 가리키는 것을 조작할 수 있다.
this 의 값
-global scope 에서 사용될 때 : 전역 객체(window 객체)
-함수에서 사용될 때 : 전역 객체
-객체에 속한 메소드에서 사용될 때 : 메소드가 속한 객체
-객체에 속한 메소드의 내부함수에서 사용될 때 : 전역 객체
-생성자에서 사용될 때 : 생성자로 인해 생성된 새로운 객체
ex) function Person(){}, var p = new Person(); // this : Person
1) 함수 직접 호출 :
2) 메서드 호출 : 객체의 메서드 호출
3) 생성자 호출 : 생성자 함수 호출
4) 간접 호출 : call, apply(함수 객체 메서드) 등으로 함수 간접 호출
※콜백 함수의 호출
function myFunc(){...}
myFunc();
//함수 직접 호출
const o = {
name : 'kim',
printName : function(){console.log(this.name),}
o.printName();
//메서드 호출
funtion Person(name){
this.name = name
this.printName = function(){
console.log(this.name)}
}
const p = new Person('kim')
//생성자 호출
setTimeout(p.printName.bind(p), 1000)
//간접 호출
//bind() this변수에 해당되는 객체를 메서드에 묶어주는 함수
// 위의 p 객체를 printName메서드에 묶어줘서 printName의 this값이 p의 this값을 갖도록 함(이 경우 p)
let o = {
name : 'kim'
f1 : () =>{
console.log("[f1] this : ", this);
},
// f1 : '화살표 함수' 호출 시 this는 함수가 생성된 환경을 가리키도록 **고정된다**
f2 : function (){
console.log("[f2] this : ", this);
},
};
// f2 : '일반 함수' 호출 시 this는 호출된 환경을 가리키며 this는 **동적으로 바뀔 수 있다.**
// f2 : 객체의 메서드로 호출될 때 객체가 this로 할당된다.
o.f1(); // this : global
o.f2(); // this : o
setTimeout(o.f1, 10); // this : global
setTimeout(o.f2, 20); // this : global
https://velog.io/@padoling/JavaScript-%ED%99%94%EC%82%B4%ED%91%9C-%ED%95%A8%EC%88%98%EC%99%80-this-%EB%B0%94%EC%9D%B8%EB%94%A9
https://sangjuntech.tistory.com/24
화살표 함수를 호출시에는 this라는 변수가 존재하지 않으므로 상위 스코프에서 탐색을 하게 되어 스코프가 global이 된다.
let o = {
name : 'kim',
printName : function(){console.log("나는 ", this.name);},
};
o.printName(); // 나는 kim
- 객체에 속한 메소드에서 사용될 때 this 는 메소드가 속한 객체를 가리킨다
setTimeout(o.printName, 10); // 나는 undefined
- 객체 내 메서드의 내부의 this는 전역 객체를 가리킨다
setTimeout(o.printName.bind(o), 20); // 나는 kim
- bind 함수를 이용해 this변수가 o를 가리키도록 컨텍스트를 동적 바인딩한다.
-bind, call, apply 등의 함수로 조작한다
-setTimeout은 함수 호출과는 다른 콜백 호출이다
-prinName 메서드는 bind 함수를 이용해 this변수가 o를 가리키도록 컨텍스트를 동적 바인딩한다.
/* 생성자 함수 방식 */
function createObject() {
this.myFunc = function () {
console.log("myFunc this:", this);
return function () { console.log("myFunc return this:", this) };
};
}
const o = new createObject();
o.myFunc().bind(o)(); // bind 메서드를 사용해 o객체로 고정시킵니다.
// myFunc this: createObject {...}
// myFunc return this: createObject {...}
/* 객체 리터럴 방식 */
const o = {
myFunc: function () {
console.log("myFunc this:", this)
return function () { console.log("myFunc return this:", this) }
},
};
o.myFunc().bind(o)(); // bind 메서드를 사용해 o객체로 고정 그리고 함수를 실행
// myFunc this: myFunc {...}
// myFunc return this: myFunc {...}
2) apply, call
-call 메서드는 인수 목록을 받고, apply 메서드는 인수 배열을 하나 받는다.
ex) call(this, var1, var2, var3, …) / apply(this, [ el, el2, el3, … ])
/* 생성자 함수 방식 */
function createObject() {
this.myFunc = function () {
console.log("myFunc this:", this);
return function () { console.log("myFunc return this:", this) };
};
}
const o = new createObject();
o.myFunc().call(o, null); // call 메서드를 사용해 o객체로 고정시킨 후 함수 실행
// myFunc this: createObject {...}
// myFunc return this: createObject {...}
o.myFunc().apply(o, null); // apply 메서드를 사용해 o객체로 고정시킨 후 함수 실행
// myFunc this: createObject {...}
// myFunc return this: createObject {...}
/* 객체 리터럴 방식 */
const o = {
myFunc: function () {
console.log("myFunc this:", this)
return function () { console.log("myFunc return this:", this) }
},
};
o.myFunc().call(o, null); // call 메서드를 사용해 o객체로 고정시킨 후 함수 실행
// myFunc this: myFunc {...}
// myFunc return this: myFunc {...}
o.myFunc().apply(o, null); // apply 메서드를 사용해 o객체로 고정시킨 후 함수 실행
// myFunc this: myFunc {...}
// myFunc return this: myFunc {...}
bind, call, apply는 일반 함수 호출에도 원하는 객체를 가리킬 수 있다.
const o = {
name: "Elice",
}
function myFunc() {
console.log(this);
}
myFunc() // window {...}
myFunc.bind(o)() // {name: 'Elice'}
myFunc.call(o, null) // {name: 'Elice'}
myFunc.apply(o, null) // {name: 'Elice'}
1) 화살표 함수
-익명 함수로만 만들 수 있다.
-생성자로 사용할 수 없다.
-스스로의 this, argument 를 가지지 않는다.
-return하지 않아도 값이 반환된다.
화살표 함수의 this는 '함수가 정의된 스코프에 존재하는' this 를 가리킨다. 즉 자신의 상위에 있는 스코프의 this를 가리킨다.
-생성될 때 this 가 결정되며 이 값을 계속 유지한다.
-화살표 함수가 어떻게 사용되건, 호출되건, this 는 바뀌지 않는다.
2) 일반 함수
-일반 함수의 this는 '새롭게 생성된 실행 컨텍스트'를 가리킨다. 즉 함수가 호출된 컨텍스트를 가리킨다.
const o = {
method(){
console.log("context : ", this) // o
let f1 = function (){
console.log("[f1] this : ", this)
}
let f2 = () => console.log("[f2] this : ", this)
f1() // global 만약 strict mode일 경우 undefined
f2() // o
},
};
o.method()
-일반 함수 f1()은 실행될 때 새로운 컨텍스트를 생성한다.
- 이때 f1에 바인딩된 컨텍스트가 없으므로 this는 global을 가리킨다.??
-화살표 함수 f2()의 this는 그 함수를 호출하는 환경을 가리킨다. 즉, 이때 this 변수는 부모의 컨텍스트를 가리키므로 this는 o가 된다.
-어떤 경우에도 this 값을 일정하게 유지해야 할 때 사용
window.name = 'Kim'
let o = {name : 'lee'}
let arrowFunction = (prefix) => console.log(prefix + this.name)
arrowFunction('Dr. ') // Dr. Kim
arrowFunction.bind(o)('Dr. ') // Dr. Kim
arrowFunction.call(o, 'Dr. ') // Dr. Kim
arrowFunction.apply(o, 'Dr. ') // Dr. Kim