2. this가 이런거로군
주요 개념 및 내용
1장에서 언급했듯이 호출하는 시점이 중요!
그 연장선으로 4가지 규칙 암기 함수호출은 callstack
구조로 쌓이게 되므로 그 호출 순서도 중요
this가 바인딩 되는 규칙
명시적
객체를 명확히 전달함
call, apply(obj,배열타입), bind
function foo() { console.log(this.a); // this = obj }; var obj = {a:2}; foo.call(obj); // 2 : 객체(obj)를 명시적으로 넘김 // 객체가 아닌 원시값 (String, Number, Boolean) 넘기 경우 -> new String(), new Number(), new ~ 호출
하드바인딩 소실되는 경우 this를 완전 명확히 바인딩 시킴 (꼼수)
function foo4() { console.log(this.a); } var obj33 = { a: 25 }; var bar = function () { foo.call(obj33); // 하드바인딩 }; bar(); //25
new
6장 프로토타입에서 보강
JS
new
class 지향과 무관 일반함수에 불과 !!new -> 함수를 생성하는 호출
(새객체가 만들어진다! -> this로 바인딩된다!)function foo44(a) { this.a = a; // this -> 새로 생성된 객체를 가르킨다 this = bar } var bar = new foo44(22); console.log(bar.a); // 22 : this = bar (new for44-> 새객체(함수) 생성 -> bar에 바인딩)
암시적
컨텍스트 객체를 통한 바인딩
function foo2() { console.log(this.a); // this = obj }; var obj2 = { a: 42, foo2: foo2 }; var obj = { a: 4, foo2: foo2, // obj.foo2 = foo2 obj2: obj2 }; obj.foo2(); // 4 obj.obj2.foo2(); // 42 : 하부에서부터 탐색을하기 때문 var bar = obj.foo2; var a = "전역쓰~"; // 암시적 소실 -> obj가 객체가 아님 bar(); // undefined -> 이때 호출은 그냥 foo2 호출가 동일해지면서 기본바인딩 적용 : this = global ()
기본
가장 기본규칙 렉시컬 스코프
function foo(){ console.log(this.a); // this => global } var a = 2; // foo(); // undefined / 엄격모드:에러 -> 호출스코프 : 전역, foo this -> global
주의 사항
바인딩 우선순위
명시(하드) > new > 암시 > 기본 순서
예외 사항
this 무시
: null, undefined 인자로 ->
기본바인딩 적용
function foo55() { console.log(this.a55); } var a55 = 2; foo55.call(null); // this 무시 : this -> global foo55.call(a55); // ?? 원시 값 a55 -> Number -> this? prototyp
간접레퍼런스
참조값을 통해 호출되므로 원 함수를 가르키게 되는 상항 -> this는 그래서
기본바인딩
이 이루어짐소프트 바인딩
테스트 코드
(function () {
// 기본 바인딩
console.log("====== 기본 바인딩 ======");
function foo() {
console.log(this.a); // 함수 자신 아님, this = global
}
var a = 2;
foo(); // undefined
// 암시적 바인딩
console.log("====== 암시적 바인딩 ======");
function foo2() {
console.log(this.a); // this = obj
}
var obj2 = {
a: 42,
foo2: foo2
};
var obj = {
a: 4,
foo2: foo2, // obj.foo2 = foo2
obj2: obj2
};
obj.foo2(); // 4
obj.obj2.foo2(); // 42
var bar = obj.foo2;
var a = "전역쓰~";
bar(); // undefined -> 이때 호출은 그냥 foo2 호출가 동일해지면서 기본바인딩 적용 : this = global
// 명시적 바인딩
console.log("====== 명시적 바인딩 ======");
function foo3() {
console.log(this.a); // this = obj3
}
var obj3 = {
a: 30
};
foo3.call(obj3); // 30 (obj3 명시)
// 하드 바인딩
console.log("====== 하드 바인딩 ======");
function foo4() {
console.log(this.a);
}
var obj33 = {
a: 25
};
var bar = function () {
foo.call(obj33); // 하드바인딩
};
bar(); //25
// new 바인딩
console.log("====== new 바인딩 ======");
function foo44(a) {
this.a = a; // this -> 새로 생성된 객체를 가르킨다 this = bar
}
var bar = new foo44(22);
console.log(bar.a); // 22 : this = bar (new for44-> 새객체(함수) 생성 -> bar에 바인딩)
// this 무시
console.log("====== this 무시 ======");
function foo55() {
console.log(this.a55);
}
var a55 = 2;
foo55.call(null); // this 무시 : this -> global
foo55.call(a55); // ??
// 에로우 함수의 this -> 전역객체를 따른다 -> 사용하지말자
console.log("======= 에로우 함수 =======");
function foo5() {
return (a) => {
console.log(this.a);
};
}
var obj = {a: 1};
var obj2 = {a: 2};
var bar = foo5.call(obj);
bar.call(obj2);
// setTimeout에서의 에로우 함수 this 활용한 꼼수
function foo6() {
setTimeout(() => {
console.log(this.a);
}, 100);
}
var obj3 = {a: 3};
foo6.call(obj3);
// var self = this를 활용한 꼼수
function foo7() {
var self = this;
setTimeout(function () {
console.log(self.a);
},100);
}
var obj4 = {a: 4};
foo7.call(obj4);
})();
Last updated