본문 바로가기

Sparta/TIL

24.01.09 TIL - this(2)

명시적 this 바인딩

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

 

1. call 메서드

a. 호출 주체인 함수를 즉시 실행

b. call명령어를 사용하여, 첫 번째 매개변수에 this로 binding할 객체를 넣어주면 명시적으로 binding할수 있다.

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. apple 메서드

a. call 메서드와 완전히 동일.

b. 차이점은 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

 

 

3. call / apply 메서드 활용

1)유사배열객체

객체에는 배열 메서드를 직접 적용할 수 없다. 하지만 key가 0 또는 양의 정수인 프로퍼티가 존재하고 length 프로퍼티의 값이 0 또는 양의 정수인 객체, 즉 유사배열 객체는 call 또는 apply 메서드를 이용해 배열 메서드를 차용할 수 있다.
단, 문자열의 경우 length 프로퍼티가 읽기 전용이므로 원본 문자열에 변경을 가하는 메서드(push, pop, shift, unshift, splice 등)는 에러를 출력하고, concat 처럼 대상이 반드시 배열이어야 하는 경우에는 에러는 출력되지 않지만 제대로된 결과를 얻을 수 없다. 유사배열객체 또는 순회 가능한 모든 종류의 데이터 타입을 배열로 전환하는 Array.from 메서드가 ES6에 도입 되기도 했다.

 

=> slice() 함수

slice() 함수는 배열로부터 특정 범위를 복사한 값을 담고 있는 새로운 배열을 만드는 데에 사용. 첫번째 인자로 시작 인덱스, 두번째 인자로 종료 인덱스를 받으며, 시작부터 종료까지 값을 복사하여 반환한다.

//객체에는 배열 메서드를 직접 적용할 수 없어요.
//유사배열객체에는 call 또는 apply 메서드를 이용해 배열 메서드를 차용할 수 있어요.
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' ]

 

 

2)Array.from 메서드 (ES6)

// 유사배열
var obj = {
	0: 'a',
	1: 'b',
	2: 'c',
	length: 3
};

// 객체 -> 배열
var arr = Array.from(obj);

// 찍어보면 배열이 출력됩니다.
console.log(arr);

 

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

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.apply(this, [name, gender]); // 여기서 this는 employee 인스턴스!
	this.company = company;
}
var kd = new Student('길동', 'male', '서울대');
var ks = new Employee('길순', 'female', '삼성');

Student, Employee 모두 Person임. name과 gender 속성 모두 필요하다. 그러니 Student와 Employee 인스턴스를 만들 때마다 세가지 속성을 모두 각 함수에 넣기보다는 Person이라는 생성자 함수에 별도로 빼는게 더 좋음

 

4)binding 메서드

a.call과 비슷해보이지만 call과는 달리 즉시호출하지 않고 넘겨받은 this 및 인수들을 바탕으로 새로운 함수를 반환.

b. 함수에 this를 미치 적용하고, 부분 적용함수를 구현할 때 용이

c. 예시

var func = function (a, b, c, d) {
	console.log(this, a, b, c, d);
};
func(1, 2, 3, 4); // window객체

// 함수에 this 미리 적용
var bindFunc1 = func.bind({ x: 1 }); // 바로 호출되지는 않아요! 그 외에는 같아요.
bindFunc1(5, 6, 7, 8); // { x: 1 } 5 6 7 8

// 부분 적용 함수 구현
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

d.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

 

'Sparta > TIL' 카테고리의 다른 글

24.01.11 TIL - 콜백함수(1)  (2) 2024.01.11
24.01.10 TIL-Git  (1) 2024.01.10
24.01.08 TIL - This(1)  (1) 2024.01.08
24.01.05 누네띠조 5일차 - 실행 컨텍스트  (0) 2024.01.05
23.01.03 누네띠조 3일차 - 불변성  (0) 2024.01.03