자바스크립트에서 모든 함수들이 실행할때마다 함수내부에서 this 라는 객체가 추가된다. this가 참조하는 대상은 함수가 호출하는 방식 마다 다르다.
var myObject = {
name: "foo",
sayName: function() {
console.log(this); // 여기서 this는 myObject를 참조
}
};
myObject.sayName();
// console> Object {name: "foo", sayName: sayName()}
객체에서 프로퍼티 가 함수면 메소드 라고 칭한다.
메소드 안에서 호출하는 this는 메소드 를 포함한 객체를 가르킨다.
Object.Function() 이렇게 메소드로 호출이될때 “ . “(점)바로앞에있는 객체에게 바인딩이 됩니다. 이렇게 바인딩되는 방식을 암시적 바인딩이라고 합니다.
암시적 바인딩으로 사용할때는 저희가 조심히 다뤄야할 부분이 있습니다 바로 메소드를 콜백으로 넘겨줄때 입니다
const obj={
name: 'sungmin',
getName() {
return this.name;
}
}
function showReturnValue(callback){
console.log(callback());
}
showReturnValue(obj.getName); //undefined
위 예제를 보시면
callback 이라는 인자가 obj.getName()의 reference (참조값)복제를 했다고 알 수 있습니다. 그래서 callback 은 obj.getName()이란 같은 참조값을 가지고 사용을 한다는것 을 알 수 있습니다. 보시다시피 아예 똑같은 참조값을 통해서 getName()을 참조하는데 왜 이런방식으로 진행하면 this값이 제대로 바인딩이 되지 않는것일까요?
그이유는 바로 “.”(점)연산 때문이다 “.” 을 사용하면 참조타입(Reference Type)이라는 특별한 타입을 사용하게 됩니다.
참조타입은 1. base:객체 2. name:프로퍼티 이름 3. strict: 엄격모드 true
이렇게 세가지 정보를 가지고 있습니다.
그런식으로 obj.getName 이런식으로 된 상태면 (base: obj , name: getName, strict: true) 참조타입은 이런식으로 설정이 됩니다. 여기서 바로 obj.getName()으로 호출을 하게 되면 this가 base 프로퍼티인 obj 를 가리키게 됩니다. 그래서 이러한 방식을 암시적 바인딩이라고 불리웁니다 . 하지만 저희가 점연산이 아닌 위 예제처럼 callback 으로 넘겨서 호출을 하게되면 암시적으로 바인딩된 객체가 휘발이 됩니다. 이런식으로 한두번만 걸쳐도 사라지는 암시적 바인딩을 해결하기 위해서 명시적 바인딩 해주는 방식이 자바스크립트에 있습니다 그 방법은 바로 bind, call, apply 방식으로 명시적 바인딩을 가능하게 해줍니다.
var value = 100;
var myObj = {
value: 1,
func1: function() {
console.log(`func1's this.value: ${this.value}`);
var func2 = function() {
console.log(`func2's this.value ${this.value}`);
};
func2();
}
};
myObj.func1();
// console> func1's this.value: 1
// console> func2's this.value: 100
메소드 가 아닌 함수로 안에서 this 가 호출이 될때는 this는 전역객체가 바인딩된다.
var Person = function(name) {
console.log(this);
this.name = name;
};
var foo = new Person("foo"); // Person
console.log(foo.name); // foo
new 연산자로 함수를 생성할때는 this는 자기자신을 바인딩한다,
new 연산자로 새로운 객체가 생성이된다(인스턴스 생성).
const tom = {
name: "tom",
age: 25,
presentation: function (style, message) {
console.log("style:"+style+"message:"+message
"name:"+this.name+"age:"+this.age);
},
};
tom.presentation("hip","hello")
const jane={
name: "jane",
age: 25,
};
tom.presentation.call(jane, "friendly", "afternoon");
// style:friendly message:afternoon name:jane age:25
tom.presentation.apply(jane, ["friendly", "afternoon"]);
// style:friendly message:afternoon name:jane age:25 (위랑 같은결과)
let johnFriendy = tom.presentation.bind(jane);
//bind method -> this를 jane 으로 변경 -> 함수를 실행하지 않는다.
johnFriendy("friendly", "moring");
// style:friendly message:afternoon name:jane age:25
new > 명시적 > 암시적 > 기본