자동으로 부여되는 상황별 this 규칙을 깨고 별도의 값을 저장하는 방법
call
apply
bind
호출 주체인 함수를 즉시 실행함
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
x=1이라는 객체가 this로 바인딩
var obj = {
a: 1,
method: function (x, y) {
console.log(this.a, x, y);
}
};
//method 함수 안의 this는 항상 obj!
obj.method(2, 3); // 1 2 3
obj.method.call({ a: 4 }, 5, 6); // 4 5 6
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
배열과 유사한 형태의 객체
반드시 length가 필요함
배열로부터 특정 범위를 복사한 값들을 담고 있는 새로운 배열을 만드는데 사용
첫번째 인자 : 시작 index
두번째 인자 : 종료 index
시작부터 종료 index까지 값 복사한 걸 반환
//객체에는 배열 메서드를 직접 적용할 수 없음
//유사배열객체에는 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' ]
객체 -> 배열로 바꾸는 메서드
// 유사배열
var obj = {
0: 'a',
1: 'b',
2: 'c',
length: 3
};
// 객체 -> 배열
var arr = Array.from(obj);
// 찍어보면 배열이 출력
console.log(arr);
Student
, Employee
모두 Person
에 포함됨. name과 gender 속성도 모두 포함이 된다. 세 가지 속성을 모두 각 생성자 함수에 넣기 보다는 Person
이라는 생성자 함수를 따로 만들어서 빼는게 더 적합 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', '삼성');
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);
//효율
var numbers = [10, 20, 3, 16, 45];
var max = Math.max.apply(null, numbers);
var min = Math.min.apply(null, numbers);
console.log(max, min);
// 펼치기 연산자(Spread Operation)를 통하면 더 간편하게 해결도 가능해요
const numbers = [10, 20, 3, 16, 45];
const max = Math.max(...numbers);
const min = Math.min(...numbers);
console.log(max min);
call이랑 비슷하지만 즉시 호출하지 않고 this 및 인수들을 바탕으로 새로운 함수를 반환하는 메서드
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
1) bind를 적용해서 새로 만든 함수는 name에 접두사가 붙음 -> 추적이 쉬움
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
2) this를 내부함수나 콜백 함수에 전달하기
2-1) 내부함수
메서드의 내부에서 this를 그대로 사용
```js
var obj = {
outer: function() {
console.log(this); // obj
var innerFunc = function () {
console.log(this);
};
// call을 이용해서 즉시실행하면서 this를 넘겨줌
innerFunc.call(this); // obj
}
};
obj.outer();
```
```js
var obj = {
outer: function() {
console.log(this);
var innerFunc = function () {
console.log(this);
}.bind(this); // innerFunc에 this를 결합한 새로운 함수를 할당
innerFunc();
}
};
obj.outer();
```
2-2) 콜백함수
- 함수가 인자로 전달될 때에는 함수 자체로 전달 -> this 유실
``` js
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();
```
var obj = {
outer: function () {
console.log(this);
var innerFunc = () => {
console.log(this);
};
innerFunc();
};
};
obj.outer();