heyday2024 님의 블로그
[JS 기초 문법 3주차(3)] 실행 컨텍스트의 세번째 요소, ThisBindings 본문
- 실행 컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체이다.
- 그 객체 안에는 3가지가 존재한다.
✓ VariableEnvironment ✓ LexicalEnvironment ✓ ThisBindings
객체 지향 언어에서의 this = 클래스로 생성한 인스턴스
자바스크립트에서는 this가 어디에서나 사용될 수 있음!!!
this는 실행 컨텍스트가 생성될 때 결정됨(this를 bind한다(=묶는다))
다시 말하면. this는 함수를 호출할 때 결정된다.
상황에 따라 달라지는 this:
1. 전역 공간에서의 this
- 전역 공간에서 this는 전역 객체를 가리켜요.
- 런타임 환경에 따라 this는 window(브라우저 환경) 또는 global(node.js 환경)를 각각 가리킵니다.
- 런타임 환경? javascript로 만들어놓은 프로그램이 구동중인 환경을 말하죠.
- 현재 node 파일이름.js로 vscode 상에서 구동하고 있으니 그 환경은 node 환경이라고 할 수 있음. html 파일 안에 숨겨놓아서 크롬브라우저 등에서 연다고 한다면 브라우저 환경이 됨.
2. 메서드로서 호출할 때 그 메서드 내부에서의 this
- 함수 vs 메서드
- 둘 다 기능을 수행한다는 면에서 비슷하지만, 다른 점이 있음!!
- 바로, 독립성!!!!!!
함수는 그 자체로 호출되면 기능함!! ----> 그래서 함수는 호출 시 주체가 없음으로 this는 전역 객체가 됨!!
함수명();
메서드는 자신을 호출할 대상 객체가 있어야함!! (그 객체에 대한 동작을 수행함)
---> 메서드를 호출하는 주체가 있기 때문에 this는 그 주체가 됨!!!!
객체.메서드명();
<예시: 함수 vs 메서드 -- this의 할당>
// CASE1 : 함수
// 호출 주체를 명시할 수 없기 때문에 this는 전역 객체를 의미해요.
var func = function (x) {
console.log(this, x);
};
func(1); // Window { ... } 1
//node.js 환경이라면 global{}임.
// CASE2 : 메서드
// 호출 주체를 명시할 수 있기 때문에 this는 해당 객체(obj)를 의미해요.
// obj는 곧 { method: f }를 의미
var obj = {
method: func,
};
obj.method(2); // { method: ƒ } 2
- 함수는 호출 시 주체가 없으므로 this는 전역객체(브라우저 환경이라면 window, 노드 환경이라면 global)
- 메서드는 호출 시 주체가 있으므로 this는 그 호출한 주체(위의 예시에서는 obj가 됨.)
그렇다면 함수와 메서드의 구분 기준은?
앞에서 말했듯 주체가 있는지 확인: 메서드는 . 또는 객체인 경우 대괄호([]) 로 호출됨!!!
var obj = {
method: function (x) { console.log(this, x) }
};
obj.method(1); // { method: f } 1
obj['method'](2); // { method: f } 2
- obj는 method의 주체임으로 this는 obj, 객체라면 [] 로도 메서드 호출 가능.
연습:
var obj = {
methodA: function () { console.log(this) },
inner: {
methodB: function() { console.log(this) },
}
};
//. 과 [] 로 obj는 메서드를 호출중
obj.methodA(); // this === obj
obj['methodA'](); // this === obj
obj.inner.methodB(); // this === obj.inner
obj.inner['methodB'](); // this === obj.inner
obj['inner'].methodB(); // this === obj.inner
obj['inner']['methodB'](); // this === obj.inner
3. 함수로서 호출할 때 그 함수 내부에서의 this
- 함수 내부에서의 this
- 함수는 호출 주체가 없기 때문에, 호출 시 this는 지정되지 않음.
- 실행컨텍스트를 활성화할 당시 this가 지정되지 않은 경우, this는 전역 객체를 의미
- 따라서, 함수로서 ‘독립적으로’ 호출할 때는 **this는 항상 전역객체를 가리킨다**👍
- 메서드의 내부함수에서의 this
- 예외는 없습니다! 메서드의 내부라고 해도, 함수로서 호출한다면 this는 전역 객체를 의미!
var obj1 = {
outer: function () {
console.log('Test =>' , this); // obj1
var innerFunc = function () {
console.log("Test =>", this); // global
};
innerFunc();
var obj2 = {
innerMethod: innerFunc,
};
obj2.innerMethod(); //obj2
},
};
obj1.outer();
this 바인딩에 관해서는 함수를 실행하는 당시의 주변 환경(메서드 내부인지, 함수 내부인지)은 중요하지 않고, 오직 해당 함수를 호출하는 구문 앞에 점 또는 대괄호 표기가 있는지가 관건이라는 것을 알 수 있습니다.
- 메서드 내부 함수에서의 this 우회
- 어떤 객체 내부에 this가 독립적인 함수에 의해 호출되어도 this는 전역객체를 가리킨다라는 부분이 개발자들에게 불편할 수도 있다. 객체 내부에 그 흐름에 맞게 this의 주체를 그 해당 객체로 유지시키기 위한 우회법이 존재한다.
<메서드 내부 함수에서의 this 우회법>
a. 변수를 활용하는 법: 내부 스코프에 이미 존재하는 this를 별도의 변수(ex: self)에 할당하는 법
var obj1 = {
outer: function() {
console.log(this); // (1) { outer: ƒ }
// AS-IS: 현재 상태
var innerFunc1 = function() {
console.log(this); // (2) 전역객체
}
innerFunc1(); //독립적으로 호출된 함수 임으로 함수가 객체 내부에 있어도, this는 전역 객체 가리킴
// TO-BE: 목표로하는 미래 상태
var self = this; //객체를 가리키는 this를 미리 self라는 변수에 할당
var innerFunc2 = function() {
console.log(self); // (3) { outer: ƒ } //this가 아니 그 할당한 변수인 self 출력
};
innerFunc2();
}
};
// 메서드 호출 부분
obj1.outer();
let obj1 = {
outer: function (){
const inner = function () {
console.log(this);
}
console.log("첫번쨰:")
inner();
const self = this;
const inner2 = function () {
console.log(self);
}
console.log("두번쨰:")
inner2()
}
}
obj1.outer();
첫번쨰:
<ref *1> Object [global] {
global: [Circular *1],
clearImmediate: [Function: clearImmediate],
setImmediate: [Function: setImmediate] {
[Symbol(nodejs.util.promisify.custom)]: [Getter]
},
clearInterval: [Function: clearInterval],
clearTimeout: [Function: clearTimeout],
setInterval: [Function: setInterval],
setTimeout: [Function: setTimeout] {
[Symbol(nodejs.util.promisify.custom)]: [Getter]
},
queueMicrotask: [Function: queueMicrotask],
structuredClone: [Function: structuredClone],
atob: [Getter/Setter],
btoa: [Getter/Setter],
performance: [Getter/Setter],
fetch: [Function: fetch],
crypto: [Getter],
obj1: { name: 'hi', age: 23, outer: [Function: outer] }
}
두번쨰:
{ name: 'hi', age: 23, outer: [Function: outer] }
- 이처럼 직접 코드 돌려보면 알수 있듯이, this를 특정 변수에 할당해서 그 변수ㅡ출력하면 메서드 없이 객체 내부의 독립적인 함수를 이용해서도 this를 해당 객체로 출력할 수 있었다.
b. 화살표 함수(= this를 바인딩하지 않는 함수):
- ES6에서 처음 도입된 화살표 함수는, 실행 컨텍스트를 생성할 때 this 바인딩 과정 자체가 없다(따라서, this는 이전의 값(상위값) 이 유지가됨.
- 애초에 ES6에서 화살표 함수가 도입된 이유: 객체 메서드 내부에서 this가 전역객체를 바라보는 문제 때문!
- 일반 함수와 화살표 함수의 가장 큰 차이점? this binding 여부가 가장 적절한 답.
var obj = {
outer: function() {
console.log(this); // (1) obj
var innerFunc = () => {
console.log(this); // (2) obj
};
innerFunc();
}
}
obj.outer();
- 원래 객체의 메서드 내부에 화살표함수가 아닌 그냥 함수를 사용했다면, 그 메서드 내부에서 해당 함수 호출 시 객체를 주체로 갖지 못하고(유실하고) 전역객체를 가리켰을텐데, 화살표함수를 사용해서 this의 이전값을 유지 시켜 this가 객체인 obj를 가리키게함.
4. 콜백 함수 호출 시 그 함수 내부에서의 this
콜백함수: 어떤 함수 또는 메서드의 인자(매개변수)로 넘겨주는 함수
콜백함수도 함수이기 때문에, 마찬가지로!!!
화살표 함수, 메서드도 아닌 독립적으로 호출되는 함수라서 호출 주체가 없음.
즉, 당연히 this가 전역객체를 참조함.
하지만!!! 예외적으로 콜백함수를 넘겨받은 함수 자체가 이미 정해진 규칙에 의해 그 대상을 참조하게되어있다면, this는 그 대상을 가리킴. (addEventListener같은 것)
즉, 콜백함수 내부의 this는 해당 콜백함수를 넘겨받은 함수(메서드)가 정한 규칙에 따라 값이 결정됨.
// 별도 지정 없음 : 전역객체
setTimeout(function () { console.log(this) }, 300);
// 별도 지정 없음 : 전역객체
[1, 2, 3, 4, 5].forEach(function(x) {
console.log(this, x);
});
// addListener 안에서의 this는 항상 호출한 주체의 element를 return하도록 설계되었음
// 따라서 this는 button을 의미함
document.body.innerHTML += '<button id="a">클릭</button>';
document.body.querySelector('#a').addEventListener('click', function(e) {
console.log(this, e);
});
- setTimeout 함수: function () {console.log(this)}는 콜백함수로 여기서의 this는 주체 대상이 없으므로 전역객체인 window(node환경이라면 global)를 가리킴.
- forEach 메서드의 콜백 함수(function(x) 부분)를 호출할 때 대상이 될 this를 지정하지 않으므로, this는 곧 window객체(node환경일 떈 global)
- 예외 메서드: addEventListner 메서드는 콜백 함수(function(e)부분) 호출 시, 항상 호출한 주체의 element를 this가 상속하도록 이미 설계됨. 그러므로, 여기서 this는 addEventListner의 앞부분(button 태그)으로 정확히는 button을 의미함.
자, 그럼 위에서 배운 것처럼 화살표 함수는 thisBinding은 안하는 함수라던데, 그럼, 화살표함수를 콜백함수로 쓰면, this가 전역객체를 가리키지 않고 호출한 그 객체를 가리키지 않을까?????
그래서 코드를 짜서 비교해봤다.
5. 생성자 함수 내부에서의 this
생성자(constructor) : 구체적인 인스턴스를 만들기 위한 일종의 틀
(같은 틀/형식에 외부로부터 받아지는 다른 값만 넣어 계속 찍어내어 생성시키는 틀과 같은 느낌...)
- 공통 속성들이 이미 준비돼 있음.
var Cat = function (name, age) {
this.bark = '야옹';
this.name = name;
this.age = age;
};
var choco = new Cat('초코', 7); //this : choco
var nabi = new Cat('나비', 5); //this : nabi
- 계속해서 새로운 인스턴스를 만들때마다 this가 변경됨.
(choco라는 인스턴스를 Cat을 이용해 만들 때 this는 choco// nabi라는 인스턴스를 Cat을 이용해 만들 때 this는 nabi)
앞서 여러 상황들에 의해 this 가 binding이 되었는데, 그런 일련의 규칙들을 깨고, 의도적(강제적)으로 this에 별도의 값을 지정하는 방법!!!!
<명시적 this 바인딩> : call, apply, bind
1. call 메서드:
this의 값을 명시적으로 지정할 수 있는 메서드. (호출 주체인 함수를 즉시 실행하는 명령어)
call명령어를 사용하여, 첫 번째 매개변수에 this로 binding할 객체를 넣어주면 명시적으로 binding할 수 있음!
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
- 원래라면, 호출하는 주체가 없는 함수여서 this가 전역객체를 가리켰을텐데,
- call을 사용해서, 맨 첫번째 인수로, 내가 명시할 this 객체를 넣어주면, this는 내가 명시한 객체를 참조하게됨.
var obj = {
a: 1,
method: function (x, y) {
console.log(this.a, x, y);
}
};
obj.method(2, 3); // 1 2 3
obj.method.call({ a: 4 }, 5, 6); // 4 5 6
2. apply 메서드:
call과 역할이 동일하나, 함수에 매개변수 넣을 때 this에 binding할 객체는 똑같이 첫번째 인수로 넣어주고 나머지 부분만 배열형태로 넘겨줘야함.
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
----- 직접 테스트-----
let obj = {
name: "obj",
method: function (a, b, c) {
console.log(`obj 메소드: ${a,b,c} 그리고 this는`, this.name)
}
}
let obj2 = {
name: "obj2",
method: function (a, b, c) {
console.log(`obj2 메소드: ${a, b, c} 그리고 this는 `, this.name);
},
};
let func = function (a, b, c) {
console.log(`fuc 함수: ${a, b, c} 그리고 this는`, this); //원래 전역객체
}
// original
console.log("오리지날-----------------------------")
obj.method(1, 2, 3); //원래 obj
obj2.method(1, 2, 3); //원래 obj2
func(1, 2, 3); //원래 전역객체
//call 메소드
console.log("call 메소드 -----------------------------")
obj.method.call(obj2, 1, 2, 3); //this는 obj2
func.call(obj, 1, 2, 3); //this는 obj
//apply 메소드
console.log("apply 메소드 -----------------------------");
obj.method.apply(obj2, [1, 2, 3]); //obj2
func.apply(obj, [1, 2, 3]); //obj
- 결과값:
오리지날-----------------------------
obj 메소드: 3 그리고 this는 obj
obj2 메소드: 3 그리고 this는 obj2
fuc 함수: 3 그리고 this는 <ref *1> Object [global] {
global: [Circular *1],
clearImmediate: [Function: clearImmediate],
setImmediate: [Function: setImmediate] {
[Symbol(nodejs.util.promisify.custom)]: [Getter]
},
clearInterval: [Function: clearInterval],
clearTimeout: [Function: clearTimeout],
setInterval: [Function: setInterval],
setTimeout: [Function: setTimeout] {
[Symbol(nodejs.util.promisify.custom)]: [Getter]
},
queueMicrotask: [Function: queueMicrotask],
structuredClone: [Function: structuredClone],
atob: [Getter/Setter],
btoa: [Getter/Setter],
performance: [Getter/Setter],
fetch: [Function: fetch],
crypto: [Getter]
}
call 메소드 -----------------------------
obj 메소드: 3 그리고 this는 obj2
fuc 함수: 3 그리고 this는 { name: 'obj', method: [Function: method] }
apply 메소드 -----------------------------
obj 메소드: 3 그리고 this는 obj2
fuc 함수: 3 그리고 this는 { name: 'obj', method: [Function: method] }
-----> call/apply 메서드 활용: this 바인딩을 위해 쓰지만 더 유용한 측면도 있음!
(1) 유사배열객체(array-like-object)에 배열 메서드 적용할 때
- 유사배열객체는 말 그대로 객체가 배열과 비슷하게 만들어진 것!
- 조건:
- 1. 반드시 length가 필요(필수)
- 2. index가 0부터 시작해서 1씩 증가해야함(선택)
- 하지만 진짜 배열처럼 push 나 slice와 같은 배열 메서드를 사용할 수는 없음....
- 조건:
그러나 call, apply 를 통해 실제 배열 메서드처럼 구현이 가능!!!!
---> call , apply는 즉시 실행 함수이기 때문에 특정 함수 기능이 수행됨과 동시 this binding으로 this자리에 해당 유사배열객체를 넣어줌으로서 기능을 수행하게끔함.
// 유사 객체 배열
let array_like_obj = {
0: "a",
1: "b",
2: "c",
length: 3
};
console.log(array_like_obj[0], array_like_obj.length) //a 3
Array.prototype.push.call(array_like_obj, "d");
console.log(array_like_obj[3]); //d
let arr = Array.prototype.slice.call(array_like_obj, 0, 2);
console.log(arr); //[ 'a', 'b' ]
사실, call/apply를 통해 객체 → 배열로의 형 변환을 할 수 있지만 이는 call/apply의 원래 의도와는 거리가 멀어서
ES6에서는 아예 Array.from을 제시함.
Array.from 은 손쉽게 유사배열객체를 배열로 만들어준다!!!
// 유사배열
var obj = {
0: 'a',
1: 'b',
2: 'c',
length: 3
};
// 객체 -> 배열
var arr = Array.from(obj);
// 찍어보면 배열이 출력됩니다.
console.log(arr);
(2) 생성자 내부에서 다른 생성자를 호출할 때 (보통 공통된 내용의 반복을 제거하기 위해서): call 사용
function Person(name, gender) {
this.name = name;
this.gender = gender;
}//공통 부분모아서 Person이라는 새로운 생성자 만들어냄.
function Student(name, gender, school) {
Person.call(this, name, gender); // 여기서 this는 student 인스턴스!
// this.name = name; //공통 부분
// this.gender = gender; //공통 부분
this.school = school;
}
function Employee(name, gender, company) {
Person.apply(this, [name, gender]); // 여기서 this는 employee 인스턴스!
// this.name = name; //공통 부분
// this.gender = gender; //공통 부분
this.company = company;
}
var kd = new Student("길동", "male", "서울대");
var ks = new Employee("길순", "female", "삼성");
- Student, Employee 모두 Person. name과 gender 속성 모두 필요함. 그래서 Student와 Employee 인스턴스를 만들 때 마다 세 가지 속성을 모두 각 생성자 함수에 넣기 보다는 Person이라는 생성자 함수를 별도로 빼는게 ‘구조화’에 도움이 더 됨.
(2) 여러 인수를 묶어 하나의 배열로 전달할 때: apply 사용
//비효율
var numbers = [10, 20, 3, 16, 45];
var max = (min = numbers[0]);
numbers.forEach(function (number) {
// 현재 돌아가는 숫자가 max값 보다 큰 경우
if (number > max) {
// max 값을 교체
max = number;
}
// 현재 돌아가는 숫자가 min값 보다 작은 경우
if (number < min) {
// min 값을 교체
min = number;
}
});
console.log(max, min);
////////// Math.max와 Math.min 메서드를 이용해 더욱 손쉽게 값을 구할 수 있음/////////
///apply 사용///
console.log(
"apply 사용",
Math.max.apply(null, numbers),
Math.min.apply(null, numbers)
);
//spread operator 사용//
console.log('spread operator 사용', Math.max(...numbers),Math.min(...numbers));
45 3
apply 사용 45 3
spread operator 사용 45 3
- 배열이 아닌 나열된 수를 인자로 갖는 Math.max, min의 메소드를 사용하기 위해 즉시실행함수인 apply를 사용할 수 있음(주체가 될 객체는 필요없으니 null로 둬도됨.)
- spread operator가 보통 더 많이 쓰이고 쉬움.
3. bind 메서드:
this를 바인딩하는 메서드. 하지만, call, apply와는 다름. 즉시 호출하지 않고, 넘겨받은 this 및 인수들을 바탕으로 새로운 함수를 반환하는 메서드.
그럼 bind를 쓰는 목적은?
1. 함수에 this를 미리 적용함
- 즉, bind를 이용해서 this를 내가 원하는 주체로 정의해놓으면, 기능은 같지만, 그 주체를 갖는 새로운 함수를 반환시켜주기 때문에, 언제든 그 함수를 재사용가능!!
2. 부분적용 함수 구현 시 용이함
- 즉, bind를 이용해서 this가 참조하는 객체뿐만 아니라 미리 인수를 부분적으로 혹은 다 미리 정해두고 사용할 수 있음.
var func = function (a, b, c, d) {
console.log(this, a, b, c, d);
};
func(1, 2, 3, 4); // global(window객체), 1,2,3,4
// 함수에 this 미리 적용
var bindFunc1 = func.bind({ x: 1 }); // 바로 호출되지는 않지만, 새로운 함수 반환.
bindFunc1(5, 6, 7, 8); // { x: 1 } 5 6 7 8
bindFunc1(7, 8, 10, 9) //{ x: 1 } 7 8 10 9
// this가 { x: 1 }를 가리키는 함수인 bindFunc1 재사용 가능!!
// 부분 적용 함수 구현
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
////////////////////////걍 궁금해서/////////////////////////////////////
/////////bind된거를 또 bind 해보기/////////////////////////////////////
let bindFunc3 = func.bind({ x: 2 }, 8, 9, 10, 3);
bindFunc3();// { x: 2 } 8 9 10 3
let test = bindFunc1.bind({ x: 6 }, 3, 4, 5);
test(1); //{ x: 1 } 3 4 5 1
let test2 = bindFunc2.bind(null, 6);
test2(1); //{ x: 1 } 4 5 6 1
- 위처럼, bind로 this가 가리키는 주체를 지정하고, 들어갈 인수를 고정할 수 있다.
- 궁금해서 bind된 함수를 다시 bind했더니, this가 가리키는 객체, 그리고 들어갈 인수가 이미 정해져있다면 이것을 수정할 수는 없고, 만약 부분적으로 인수를 고정했다면, 아직 정해지지 않은 인수들은 추가적으로 변경이 가능했다.
--> 정리하자면, bind가 이미 적용된 함수를 다시 bind할 수 있지만, this는 처음에 설정된 값에서 바뀌지 않음. 이는 bind 메서드의 동작 방식 때문임. 즉, bind는 함수의 this 값을 고정하는 역할을 하며, 그 이후에 다시 bind를 해도 이미 설정된 this 값은 변경되지 않음. 하지만 부분 적용된 인수는 계속 추가할 수 있고, 이를 통해 점진적으로 함수의 인자를 추가해 나가며 사용할 수도 있음.
bind로 만들어진 함수의 name 프로퍼티?
bind 메서드를 적용해서 새로 만든 함수는 name 프로퍼티에 ‘bound’ 라는 접두어가 붙음.
var func = function (a, b, c, d) {
console.log(this, a, b, c, d);
};
var bindFunc = func.bind({ x:1 }, 4, 5);
// func와 bindFunc의 name 프로퍼티의 차이를 살펴보세요!
console.log(func.name); // func
console.log(bindFunc.name); // bound func
--> 어떤 함수로부터 만들어졌는지 추적하기가 쉬움.
이제 call, bind, apply와 같은 명시적으로 this값을 설정하는 법을 배웠으니 우리는 이제 "상위 컨텍스트의 this를 내부함수나 콜백함수에 전달" 할 때 this를 변수에 할당해서 굳이 사용할 필요가 없어졌다(실제로도 이런식으로 잘 안씀)
위와 같은 변수를 활용용한 this 우회법 대신 아래와 같이 call이나 bind를 사용하는 게 편함.
//call 사용
var obj = {
outer: function () {
console.log(this); // obj
var innerFunc = function () {
console.log(this);
};
// call을 이용해서 즉시실행하면서 this를 넘겨주었습니다
innerFunc.call(this); // obj
},
};
obj.outer();
///////////////////////////////////////////////////////////////////////
//bind 사용
var obj = {
outer: function () {
console.log(this); // obj
var innerFunc = function () {
console.log(this);
}.bind(this);
innerFunc();
},
};
obj.outer();
보통은 bind를 더욱 많이 씀(call은 즉시 실행함수라...)
콜백함수도 bind메서드로 this를 변경가능.
var obj = {
logThis: function () {
console.log(this);
},
logThisLater1: function () {
// 0.5초를 기다렸다가 출력해요. 정상동작하지 않아요.
// 콜백함수도 함수이기 때문에 this를 bind해주지 않아서 잃어버렸어요!(유실)
setTimeout(this.logThis, 500);
},
logThisLater2: function () {
// 1초를 기다렸다가 출력해요. 정상동작해요.
// 콜백함수에 this를 bind 해주었기 때문이죠.
setTimeout(this.logThis.bind(this), 1000);
}
};
obj.logThisLater1();
obj.logThisLater2();
위에서 이미 테스트한 내용이지만, 화살표 함수는 실행 컨텍스트 생성 시, this를 바인딩하는 과정이 제외되기 때문에, 화살표함수를 콜백함수로 사용하게 되면 this 우회법으로 call apply bind 보다 더욱 편리한 방법이 될 수 있음.
(정리하자면, 이 함수 내부에는 this의 할당과정(바인딩 과정)이 아에 없으며, 접근코자 하면 스코프체인상 가장 가까운 this에 접근하게 됨)
var obj = {
outer: function () {
console.log(this);
var innerFunc = () => {
console.log(this);
};
innerFunc();
};
};
obj.outer();
JS안에서의 this에 대한 개념정리가 제대로 안 되었었는데, 확실하게 이번 기회에 this의 개념을 이해한 것 같아서 기쁘다.
'프론트엔드 부트캠프' 카테고리의 다른 글
[4주차 JS 문법(1)] 콜백함수 (제어권, this 바인딩) (1) | 2024.10.21 |
---|---|
[3주차 과제] 객체 복사, this 이해 (4) | 2024.10.20 |
Web APIs , DOM, 로컬 스토리지, 이벤트 처리 방식 (0) | 2024.10.18 |
[Github 특강] Github 이용해서 협업 과정 + 팁(dev) (2) | 2024.10.17 |
[JS 강의 2회차] 객체&배열 의 데이터 저장, 수정, 삭제, 복사 정리 (2) | 2024.10.17 |