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
})
}