this 바인딩 규칙에 이어서 명시적 바인딩 내용도 정리해보장
[규칙] - 명시적 this 바인딩이 없는 한 늘 성립한다.
- 전역 공간에서의 this 는 전역객체를 참조한다.
- 어떤 함수를 메서드로서 호출한 경우 : this 는 메서드 호출 주체를 참조한다.
- 어떤 함수를 함수로서 호출한 경우 : 전역 객체를 참조한다. (메서드의 내부 함수에서도 동일)
- 콜백 함수 내부에서의 this 는 해당 콜백 함수의 제어권을 넘겨받은 함수가 정의한 바에 따르며, 정의하지 않은 경우에는 전역 객체를 참조한다.
- 생성자 함수에서의 this 는 생성될 인스턴스를 참조한다.
[명시적 this 바인딩]
- call, apply 메서드는 this 를 명시적으로 지정하면서 함수 또는 메서드를 호출한다.
- bind 메서드는 this 및 함수에 넘길 인수를 일부 지정해서 새로운 함수를 만든다. (반환한다)
- 요소를 순회하면서 콜백함수를 반복 호출하는 내용의 일부 메서드(forEach 등)는 별도의 인자로 this 를 받기도 한다.
1-1. call 메서드
call 메서드의 호출 주체인 함수를 즉시 실행시킴
call 메서드의 첫번째 인자 = this 로 할당
나머지 인자는 실행시킬 함수의 매개변수로 전달
var func = function (a, b, c){
console.log(this, a, b, c);
}
func(1,2,3) // Window,1,2,3
func.call({x:1}, 4,5,6) // {x:1},4,5,6 -- 이경우 this.x = 1
this 에 할당할 대상을 직접 첫번째 인자로 전달
1-2. apply 메서드
call과 기능적으로 완전히 동일함. 함수의 매개변수로 전달할 인자를 배열에 담는다.
var func = function (a, b, c){
console.log(this, a, b, c);
}
func.apply({x:1}, [4,5,6]) // {x:1},4,5,6
1-3. call / apply 메서드 활용
1) 유사 배열 객체에 배열 메소드 적용하기 😲이런게 된다고
객체에 배열 메소드를 사용한 경우
key 가 0 또는 양의 정수인 프로퍼티가 존재하고 & length 프로퍼티 값이 0 또는 양의 정수일때
= 유사 배열 객체
ex. querySelectorAll() 이 반환하는 NodeList, 함수에 전달하는 arguments 등
var obj = {
0:'a',
1:'b',
2:'c',
length:3
}
Array.prototype.push.call(obj, 'd'); // 배열 메서드인 push 를 사용
console.log(obj); // {0:'a', 1:'b', 2:'c',3:'d', length:d}
var arr = Array.prototype.slice.call(obj); // 배열 메서드인 slice 사용, 얕은 복사
console.log(arr) // ['a','b','c','d']
유사 배열 객체는 배열처럼 생겼지만, 배열이 아니다 -> 배열 메서드를 직접 사용할 수 없다.
Array.prototype.push 와 같은 배열 메서드를 call이나 apply를 사용하여 적용할수 있다.
call(obj, 'd') : obj가 this로 바인딩 된다. -> Array.prototype.push 메서드가 obj에 대해 실행된다.
=> 따라서 obj는 배열처럼 다루어진다. (push 로 요소가 추가되고 length가 증가함)
*slice(start, end) 에 인자 없으면 얕은복사를 수행한다.
문자열 역시 인덱스와 length 프로퍼티를 갖기때문에 배열 메서드를 사용할 수 있다.
다만 length 프로퍼티가 읽기 전용이므로 원본 문자열에 변경을 가하는 메서드 (push, pop, shift, unshift, splice)등은 적용 시 에러 발생한다.
📍ES6 : Array.from 메서드
유사 배열 객체 또는 순회 가능한 모든 종류의 데이터 타입을 배열로 전환하는 메서드
2) 생성자 내부에서 다른 생성자 호출하기
다른 생성자와 공통된 내용이 있을 경우 반복 줄이는 방법
function Person(name, gender){
this.name = name;
this.gender = gender;
}
function Student(name, gender, school){
Person.call(this, name, gender); // 생성자 내부에서 다른 생성자 호출
this.school = school;
}
3) 여러 인수를 묶어 하나의 배열로 전달하기 - apply
하나의 배열의 원소들을 -> 여러개의 인수를 받는 메서드의 인수로 전달하고 싶을때
- apply 사용했을때
var numbers = [10, 20, 30, 41, 4];
var max = Math.max.apply(null, numbers);
var min = Math.min.apply(null, numbers);
- apply 사용하지 않으면?
numbers 배열을 순회하면서 값을 비교 후 max, min에 할당하는 방식으로 구현
📍ES6: 스프레드 연산자 (펼치기 연산자)
배열의 원소를 전달
var numbers = [10, 20, 30, 41, 4]; const max = Math.max(...numbers);
2. bind 메서드
ES5 에서 추가된 기능
call과 비슷하지만 즉시 호출하지 않는다.
(1) this 명시
넘겨받은 this 와 인수들을 바탕으로 새로운 함수를 반환하며, 반환하는 함수에 this를 등록
=> 반환한 함수를 호출할때 인자를 전달한다.
(2) name 프로퍼티
=> name 프로퍼티에 'bound 원본함수 이름' 이 저장된다 -> 코드 추적하기 수월해짐
var func = function (a,b,c){
console.log(this, a,b,c);
}
func(1,2,3); // Window, 1,2,3
var bindFunc1 = func.bind({x:1});
bindFunc1(5,6,7); // {x:1}, 5,6,7
// 부분 적용 함수 구현
var bindFunc2 = func.bind({x:1}, 4);
bindFunc2(6,7) //{x:1}, 4,6,7
bindFunc2(8,9) //{x:1}, 4,8,9
// name 프로퍼티 확인
console.log(func.name) // func;
console.log(bindFunc1.name) // bound func
(3) 상위 컨텍스트의 this를 내부함수나 콜백함수에 전달하기
상위 컨텍스트의 this 를 상속하기 위해 self 등의 변수를 사용하는 우회법 대신 사용 가능한 방법
var obj1 = {
outer : function (){
console.log(this);
var innerFunc = function (){
console.log(this);
}
innerFunc.call(this);
}
}
obj1.outer();
- call 사용 : 즉시 실행되는 함수에 this를 명시적으로 설정
var obj1 = {
outer : function (){
console.log(this);
var innerFunc = function (){
console.log(this);
}.bind(this);
innerFunc();
}
}
obj1.outer();
-bind 사용 : 즉시 실행하지 않고 새로운 함수를 반환
var obj1 = {
outer: function () {
console.log(this);
var innerFunc = () => {
console.log(this);
};
innerFunc();
}
}
obj1.outer();
- 화살표 함수 사용 : this 바인딩 과정 생략
함수 내부에 this가 없기 때문에 this 접근 시 스코프 체인상 가장 가까운 this에 접근
3. 요소를 순회하는 메서드
var report = {
sum : 0,
count: 0,
add : function (){
var args = Array.prototype.slice.call(arguments);
args.forEach(function (entry){
this.sum += entry;
++this.count;
},this) // 두번째 인자로 this 전달
},
average : function (){
return this.sum / this.count;
}
}
report.add(60, 85, 95);
console.log(report.sum, report.count, report.average);
report 객체
sum, count 프로퍼티, add, averga 메서드를 갖는다.
add 에 할당된 함수(메서드)는
arguments 를 args 배열로 반환하고, 이를 순회하면서 콜백함수 실행 : sum 과 count 값 조작
이때 콜백함수 내부의 this 는 두번째 인자로 전달한 this (add 메서드의 this)가 바인딩 된다.
report.add(60, 85, 95) 로 메서드 호출하면 => arguments => args = [60, 85, 95]
add의 this 는 호출한 주체인 report
-> args 배열에 forEach 메서드 실행
-> this.sum, this.count 에 값 할당 = report 의 sum, count 프로퍼티


자주 쓰는 배열 메서드에 두번째 인자가 있다는걸 처음 알았다 ;;
arguments는 함수 호출 시 파라미터로 전달된 값이 저장되는 유사배열 객체
- 함수 내부에서만 접근 가능
- 스프레드 연산자로 배열로 변환할수 있음
하 정말 길어따... 책을 눈으로만 훑으면 이해가 안돼서 손으로 필기를 하고, 좀 이해가 됐다 싶으면 블로그에 포스팅을 하고있다.
블로그 포스팅하면서도 새롭기도 하고 (아직 익숙지 않은 개념이라 그런지), 잘못 이해하고 있던 내용도 발견하게 된다.
어쩌면 이 내용들을 까먹을 수도있고, 면접에서 유창하게 말하지 못할수도 있다.
그렇지만 이렇게 학습한 내용이 어딘가에 남아서 다른 개념과 연결되기도하고, 운이 좋다면 기억을 잘 할수도 있을 것이다 ㅎ
한편 프로젝트 하면서는 this 라는 개념을 몰라도 딱히 불편하지 않았던게 사실이다. (혹은 그렇게 착각하고 있을지도)
지피티 말로는 콜백함수, 배열 메서드 등을 사용하는 함수형 프로그래밍 패턴에서는 this 를 직접 사용할 필요가 없고,
그러한 함수형 컴포넌트를 많이 사용하는 React 프로젝트를 주로 했기 때문에 그렇다고 한다. 리액트의 훅을 사용함으로써 this를 참조할 필요가 없다고.
그렇지만 다른 개발 언어에서도 쓰이기도 하고 자바스크립트에서도 중요한 개념인만큼 잘 알아두자고 다짐한다 ㅎ

'개발 공부 일지 > [도서] IT_개발' 카테고리의 다른 글
| [코어 자바스크립트] 비동기 제어로 콜백 지옥 탈출하기 (1) | 2025.02.25 |
|---|---|
| [코어 자바스크립트] 콜백 함수 (0) | 2025.02.25 |
| [코어 자바스크립트] this - 규칙 (0) | 2025.02.21 |
| [코어 자바스크립] 실행 컨텍스트 / 호이스팅 (1) | 2025.02.19 |
| [코어 자바스크립트] 데이터 타입 (기본형, 참조형) (0) | 2025.02.18 |