[TIL #7] 231018_this

Bora.K | 권보라·2023년 10월 18일
0

TIL

목록 보기
7/51
post-thumbnail

오늘 한 일

  • [내배캠] Javascript 문법 3주차 완강
  • 개인과제 발제 (Project.01 영화 검색 사이트 제작)
    • TMDB 오픈 API 영화 데이터 가져오기
    • 깃허브 레포지토리 생성
  • 웹 지식 특강

배운 것

1. 상황에 따라 달라지는 this

(1) 메서드의 내부 함수에서의 this 우회

  • 변수를 활용하는 방법
    내부 스코프에 이미 존재하는 this를 별도의 변수(ex : self)에 할당
var obj1 = {
	outer: function() {
		console.log(this); // (1) outer

		// AS-IS
		var innerFunc1 = function() {
			console.log(this); // (2) 전역객체
		}
		innerFunc1();

		// TO-BE
		var self = this;
		var innerFunc2 = function() {
			console.log(self); // (3) outer
		};
		innerFunc2();
	}
};

// 메서드 호출 부분
obj1.outer();
  • 화살표 함수를 활용하는 방법
    화살표 함수는 this를 바인딩하지 않음 → this는 이전의 값(상위값) 유지
var obj = {
	outer: function() {
		console.log(this); // (1) obj
		var innerFunc = () => {  // 화살표 함수는 this를 바운딩하지 않음
			console.log(this); // (2) obj
		};
		innerFunc();
	}
}

obj.outer();

(2) 콜백 함수 호출 시 그 함수 내부에서의 this

  • 콜백함수함수이므로 this전역 객체를 참조한다.
  • 콜백 함수에 별도로 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);
});

(3) 생성자 함수 내부에서의 this

  • 새로운 인스턴스(객체)를 만들기 위한 툴
  • 새로운 인스턴스를 만들 때마다 this는 달라짐



2. 명시적 this 바인딩

자동으로 부여되는 상황별 this의 규칙을 깨고 this에 별도의 값을 저장

(1) 즉시실행함수 call 메서드

call 명령어를 사용하여 첫 번째 매개변수에 this로 바인딩할 객체 삽입

  • this가 전역객체인 경우
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
  • 호출 주체가 있는 경우에도 명시적 바인딩 가능
var obj = {
	a: 1,
	method: function (x, y) {
		console.log(this.a, x, y);   // this는 항상 obj
	}
};

obj.method(2, 3); // 1 2 3
obj.method.call({ a: 4 }, 5, 6); // 4 5 6

(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

  • 유사배열객체: 배열과 유사한 형태의 객체
    • 반드시 length가 필요
    • index 번호가 0번부터 시작하여 1씩 증가
    • 객체이기 때문에 배열 메서드를 직접 적용 X → call 또는 apply 메서드 이용
      ex) push, slice
    • this를 바인딩하지 않고, this 자리에 유사배열객체 삽입
      callarray는 this를 바인딩하기 위한 것으로, 원래 목적에서는 벗어난 사용법
var obj = {
	0: 'a',
	1: 'b',
	2: 'c',
	length: 3
};
Array.prototype.push.call(obj, 'd');
console.log(obj); // { 0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4 }

var arr = Array.prototype.slice.call(obj);
console.log(arr); // [ 'a', 'b', 'c', 'd' ]
  • Array.from 메서드(ES6): 객체를 배열로 형 변환
var obj = {
	0: 'a',
	1: 'b',
	2: 'c',
	length: 3
};

var arr = Array.from(obj);

console.log(arr);   // [ 'a', 'b', 'c' ]

(3) 생성자 내부에서 다른 생성자를 호출(공통된 내용의 반복 제거)

  • 기존
function Student(name, gender, school) {
    this.name = name;
    this.gender = gender;
    this.school = school;
}

function Employee(name, gender, company) {
    this.name = name;
    this.gender = gender;
    this.company = company;
}

var kd = new Student('길동', 'male', '서울대');
var ks = new Employee('길순', 'female', '삼성');

console.log(kd);  // Student { name: '길동', gender: 'male', school: '서울대' }
console.log(ks);  // Employee { name: '길순', gender: 'female', company: '삼성' }
  • 반복 제거
function Person(name, gender) {
    this.name = name;
    this.gender = gender;
}

function Student(name, gender, school) {
    Person.call(this, name, gender);  // 여기서 this는 student 인스턴스!
    this.school = school;
}

function Employee(name, gender, company) {
    Person.call(this, name, gender);  // 여기서 this는 employee 인스턴스!
    this.company = company;
}

var kd = new Student('길동', 'male', '서울대');
var ks = new Employee('길순', 'female', '삼성');

console.log(kd);  // Student { name: '길동', gender: 'male', school: '서울대' }
console.log(ks);  // Employee { name: '길순', gender: 'female', company: '삼성' }

  • 기존
var numbers = [10, 20, 30, 40, 50];
var max = min = numbers[0];

numbers.forEach(function(number) {
    if (number > max) {
        max = number;
    }

    if (number < min) {
        min = number;
    }
})

console.log(max, min);   // 50 10
  • apply를 사용하여 간결하게 표현 가능 : Math.max Math.min 사용
var numbers = [10, 20, 30, 40, 50];

var max = Math.max.apply(null, numbers);
var min = Math.min.apply(null, numbers);

console.log(max, min);   // 50 10
  • spread operator 사용
var numbers = [10, 20, 30, 40, 50];

var max = Math.max(...numbers);
var min = Math.min(...numbers);

console.log(max, min);   // 50 10

(4) bind 메서드
call, apply와는 달리 bind는 즉시 호출하지 않음 → 새로운 함수 반환

  • 함수에 this를 미리 적용
var func = function (a, b, c, d) {
	console.log(this, a, b, c, d);
};
func(1, 2, 3, 4); // window객체 1 2 3 4
var func = function (a, b, c, d) {
	console.log(this, a, b, c, d);
};

// 함수에 this 미리 적용
var bindFunc1 = func.bind({ x: 1 });   // 바로 호출되지 않음
bindFunc1(5, 6, 7, 8); // { x: 1 } 5 6 7 8
  • 부분 적용 함수를 구현할 때 용이
var func = function (a, b, c, d) {
	console.log(this, a, b, c, d);
};

// 부분 적용 함수 구현
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
  • name 프로퍼티
    bind 메서드를 적용하여 만든 함수는 name 프로퍼티에 ‘bound’라는 접두어가 붙는다.
    → 추적하기 쉬움
console.log(func.name); // func
console.log(bindFunc.name); // bound func

(5) 화살표 함수의 예외사항

this를 바인딩하는 과정이 제외 → call, apply, bind 보다 편리한 방법

var obj = {
	outer: function () {
		console.log(this);
		var innerFunc = () => {
			console.log(this);
		};
		innerFunc();
	};
};
obj.outer();

오늘의 회고

  1. this 용법이 제일 어려운 것 같다. 두고 두고 여러 번 봐야 이해할 수 있을 듯... 전역객체, 바인딩... 아직 개념 이해가 잘 안된다. 두번 째 들을 때는 조금 더 이해할 수 있기를...

  2. 개인 과제 발제가 있었다. 바닐라 자바스크립트를 이용하여 영화 검색 사이트 제작! 어떻게 시작을 해야할지 막막하다. 우선 오픈 API 인기영화 데이터를 다운 받고, 깃허브에 레포지토리 생성해서 VS코드에 일단 넣어놨다. 시작이 반...하핳

  3. 팀원끼리 오늘 소통을 하면서 팀 약속, 목표를 설정했다. 팀명은 A-8조라서 Aeight(에-잇)
    대학 졸업 후 이런 팀 프로젝트를 해본 적이 없어서 나름 재밌...


내일 할 일

  • [내배캠] Javascript 문법 4주차 완강
  • [Project.01] 개인과제 기초 세팅 만들어 보기
profile
Frontend Engineers

0개의 댓글