
property(상태(state)를 나타냄) + 메서드(동작(behavior)
을 나타냄을 하나의 논리적인 단위로 묶은 복합적인 자료구조
메서드는 자신이 속한 객체의 상태 즉, 프로퍼티를 참조하고 변경할 수 있어야 한다. 이때 객체의 프로퍼티를 참조하려면 먼저 자신이 속한 객체를 가리키는 식별자를 참조할 수 있어야 한다
생성자 함수로 인스턴스를 생성하려면 먼저 생성자 함수가 존재해야 한다. 그리나 생성자 함수를 정의하는 시점에서는 인스턴스를 생성하기 전이므로 생성자 함수가 생성할 인스턴스를 가리키는 식별자를 모른다. 따라서 인스턴스를 가리키는 특수한 식별자가 필요하고, javascript에서는 this를 제공한다
// 생성자 함수
function Circle(radius){
???.radius=radius;
//인스턴스(circle)의 값을 초기화하기 위해 인스턴스를 가리키는 식별자가 필요하다. 그리나 정의할 때 당시에는 어떤 인스턴스를 가리킬지 모르므로 공통의 식별자를 사용할 필요가 있고, 그것이 this이다.
}
const circle=new Circle(5);
this는 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기참조변수다
javascript에서 this는 함수가 호출되는 방식에 따라 this에 바인딩 될 값이 달라진다.(strict mode또한 this 바인딩에 영향을 준다)
// 유형 1. 전역에서 .. this는 전역 객체 window를 가리킨다
console.log(this); // window
// 유형 2. 일반 함수 내부에서 .. this는 전체 객체 window를 가리킨다
// (strict mode에서는 일반함수에서 this 사용시 undefined가 바인딩 된다)
function square(number){
console.log(this); // window
return number*number;
}
// 유형 3. 객체 리터럴에서 .. 매서드 내부에서 this는 메서드를 호출한 객체를 가리킨다
const person={
name:'lee',
getName(){
console.log(this) // person
return this.name // lee
}
}
// 유형 4. 생성자 함수에서 .. this는 생성자 함수가 생성할 인스턴스를 가리킨다.
function Person(name){
this.name=name;
console.log(this);// Person {name:'kim'}
}
const myPerson=new Person('kim');
// 유형 5. Function.prototype.apply/call/bind 메소드 .. 에 의한 간접 호출
// foo 함수 내부의 인수에 의해 결정된다.
const bar={name:'bar'}
foo.call(bar);//bar
foo.apply(bar);//bar
foo.bind(bar)();//bar
다만 .. this는 객체의 프로퍼티나 메소드를 참조하기 위한 자기 참조 변수이기 떄문에 일반적으로 객체 메소드 내부 또는 생성자 함수 내부에서만 의미가 있다. 따라서 strict mode가 적용된 경우 일반함수에서 this를 사용하면 undefined가 바인딩 된다.
자기참조변수 이기 때문에 일반 함수에서의 사용은 무의미 하다. 따라서 strict mode에서는 undefined가 바인딩 된다.function foo(){
console.log(this)//window
}
foo()
function foo(){
'use strict'
console.log(this)//undefined
}
foo()
var value=1
const obj={
value:100,
foo(){
console.log(this);//obj .. {value:100, foo:f}
console.log(this.value);//100
function bar(){
console.log(this);//window .. 중첩 함수이기 때문이다
console.log(this.value);//1 .. 전역 변수 value의 값
}
}
}
방법1. this를 특정 변수가 가리키게 만드는 방법이 있다.
var value=1
const obj={
value:100,
foo(){
console.log(this);//obj .. {value:100, foo:f}
console.log(this.value);//100
function bar(){
const that=this;
console.log(that);// obj .. {value:100,foo:f}
console.log(thit.value);//100
}
}
}
방법2. Function.prototype.apply / call / bind를 사용해 콜백 함수에 명시적으로 this를 바인딩하는 방법
var value=1;
const obj={
value:100,
foo(){
setTimeout(function (){
console.log(this.value)//100
}.bind(this),1000)
}
}
방법3. 화살표 함수를 사용하면 바로 this 바인딩을 일치 시킬 수 있다.
var value=1;
const obj={
value:100,
foo(){
setTimeout(()=>console.log(this.value),1000)//100
}
}
const person={
name:'kim',
getName(){
return this.name;
}
}
console.log(person.getName())//'kim'
person 객체의 getName 프로퍼티는 person객체에 포함된 것이 아닌 독립적인 객체이다. 따라서 해당 객체는 경우에 따라 다른 객체의 메소드가 될수도 있고, 일반함수로 호출될 수도 있다.
const anotherPerson={
name:'park'
}
// 유형1. 다른 객체의 메소드로 할당
anotherPerson.getName=person.getName;
console.log(anotherPerson.getName)// park
// 유형2. 변수에 할당
const p=person.getName;
console.log(p)// ' '
// 전역에서의 this이므로 window.name의 값이 리턴된다
// 브라우저에서 window.name은 built-in 프로퍼티이고, 디폴트가 ''이다
// node.js에서는 undefined이다.
// 유형3. 프로토타입 메서드 내부에 할당
function Person(name){
this.name=name;
}
Person.prototype.getName=function(){
return this.name;
}
const me=new Person('kim');
me.getName()//kim
Person.prototype.name='park'
console.log(person.prototype.getName())// park
생성자 함수 내부의 this는 나중에 생성될 인스턴스가 바인딩된다
function Circle(radius){
this.radius=radius
this.getRadius=function(){
return this.radius;
}
}
const c1=new Circle(5);
const c2=new Circle(10);
console.log(c1.getRadius);//5
console.log(c2.getRadius);//10
(new연산자와 호출하지 않으면 생성자 함수가 아닌 일반 함수로 동작하여 undefined가 리턴된다)
첫 번째 인수로 전달한 특정 객체를 호출한 함수의 this에 바인딩한다
function getThisBinding(){
return this;
}
const thisArg={a:1};
console.log(getThisBinding());
console.log(getThisBinding.apply(thisArg));
console.log(getThisBinding.call(thisArg));
bind()는 메서드의 this와 메서드 내부의 중첩함수 또는 콜백함수의 this간 불일치를 해결학 위한 용도로 사용된다.
const person={
name:'kim',
foo(callback){
setTimeout(callback,1000);
}
}
person.foo(function(){
console.log(this.name);//해당 함수가 실행될 때의 위치는 함수 밖이기 때문에 일반함수 취급을 한다. 따라서 'kim'이 아닌 'undefined'가 리턴된다.
});
이때 bind()를 사용하면 this가 가리키는 대상을 하나로 묶을 수 있다.
const person={
name:'kim',
foo(callback){
setTimeout(callback.bind(this),1000);//bind의 첫번쨰 인자로 this를 보냈기 때문에 콜백함수 내부와 외부의 this는 같은 대상을 가리킨다
}
person.foo(funcion(){
console.log(this.name)// kim
})
}