2021. 8. 5. 15:30ㆍCSE/Java Script
<호출 패턴과 this 바인딩>
- arugments 객체 뿐만 아니라 this 인자가 함수 내부로 암묵적으로 전달됨
- 함수가 호출되는 방식인 호출 패턴에 따라 this가 다른 객체를 참조한다 (this 바인딩)
1. 객체의 메서드 호출할 때, this 바인딩
- 메서드 : 객체의 프로퍼티가 함수인 경우
- 메서드를 호출할 때, 해당 메서드 내부의 this는 메서드를 호출한 객체가 된다.
var myObject= {
name : 'foo',
sayName:function(){
console.log(this.name);
}
};
var otherObject = {
name : 'bar'
};
otherObject.sayName = myObject.sayName;
myObject.sayName(); //foo
otherObject.sayName(); //bar
2. 함수를 호출할 때 this 바인딩
- 함수 내부 코드에서 사용된 this는 전역 객체에 바인딩이 된다.
=> 브라우저의 경우 window 객체가 되고, Node.js에서는 global 객체가 된다.
- 모든 전역 변수는 전역 객체의 프로퍼티이다.
- 함수 호출에서 this 바인딩 특성은 내부 함수를 호출했을 경우에도 적용되므로, 내부 함수에서 this를 이용할 때는 주의해야 한다.
- 객체의 프로퍼티인 func1의 this는 해당 객체인 myObject에 바인딩이 되지만, 내부 함수인 func2, func3는 전역 객체에 바인딩이 된다.
=> 이를 극복하는 방법은 부모 함수의 this를 내부함수가 접근 가능한 다른 변수에 저장하는 것이다. 주로 that이라는 변수에 저장한다.
- 자바스크립트에서는 this 바인딩의 한계를 극복하려고, this 바인딩을 명시적으로 할 수 있도록 call과 apply 메서드를 제공한다.
3. 생성자 함수를 호출할 때 this 바인딩
- 자바 스크립트의 생성자 함수는 객체를 생성하는 역할을 한다
=> 기존 함수에 new 연산자를 붙여서 호출하면 해당 함수는 생성자 함수로 동작한다.
//생성자 함수
var Person = function (name){
this.name = name;
}
//생성자 함수를 통해 객체 생성
var foo = new Person('Ella');
console.log(foo.name); //Ella
** 생성자 함수가 동작하는 방식**
- 생성자 함수 코드가 실행 되기 전, 빈 객체가 생성되고, 생성자 함수 내부의 this는 해당 빈 객체를 가리킨다.
- 생성자 함수 내부에서 this를 사용해서 생성된 빈 객체에 동적 프로퍼티나 메서드를 추가할 수 있다.
- 생성자 함수에서 리턴문이 없으면 해당 객체인 this를 return한다.
** 객체 리터럴 방식 vs 생성자 함수 방식 **
- 객체 리터럴 방식 : 같은 형태의 객체를 재생성할 수 없다
- 생성자 함수 방식 : 같은 형태의 서로 다른 객체를 재생성할 수 있다.
- 객체 리터럴 방식과 생성자 함수 방식의 차이가 프로토타입 객체에 있음을 알 수 있다.
=> 왜 프로토타입 객체에 차이가 발생할까? : 자바 스크립트 객체 생성 규칙 때문
=> 자바스크립트 객체는 자신을 생성한 생성자 함수의 prototype 프로퍼티가 가리키는 객체를 자신의 프로토타입 객체로 설정한다
** 생성자 함수를 new를 붙이지 않고 호출할 경우 **
- 생성자 함수를 new 없이 호출하거나 일반 함수를 new를 붙여서 호출할 경우 오류가 발생한다.
=> 일반 함수 호출과 생성자 함수를 호출할 때 this 바인딩 방식이 다르기 때문
- 일반 함수 : this가 window 전역 객체에 바인딩
- 생성자 함수 : this 새로 생성되는 빈 객체에 바인딩
- 따라서 생성자 함수를 new 없이 호출하게 되면, this가 바인딩된 window에 동적으로 name과 gender 프로퍼티를 생성하게 되는 것이다.
=> 따라서 생성자 함수로 사용할 함수는 첫 글자를 대문자로 표기하는 네이밍 규칙을 권장한다.
+ 객체를 생성하는 별도의 코드 패턴
function A(arg){
if (!(this instanceof A))
return new A(arg);
this.value = arg ? arg : 0 ;
}
- this가 해당 함수의 인스턴스인지 확인하고 아니라면 new를 붙여서 실행한 생성자 함수 결과를 리턴하도록 한다.
4. call과 apply 메서드를 이용한 명시적인 this 바인딩
- apply()와 call() 메서드는 Function.prototype 객체의 메서드이므로 모든 함수들이 호출할 수 있다.
함수.apply(this를 바인딩할 객체, 함수에 넘겨줄 인자 배열);
함수.call(this를 바인딩할 객체, 함수에 넘겨줄 인자1, 인자2 ...);
- 이런 메서드를 호출하는 주체가 함수이기 때문에 본질적인 기능은 함수 호출이다.
=> 즉 함수.apply()의 기본적인 기능은 Person() 함수를 호출하는 것
=> Person('foo', 30) 함수를 호출하면서 this를 foo 객체에 명시적으로 바인딩하는 것을 의미한다
- 대표적인 용도 : 유사 배열 객체에서 배열 메서드 사용하는 경우
=> Array.prototype.slice() 메서드를 호출하는데, 이 때 this는 arugments 객체로 바인딩해라
=> arguments 객체가 Array.prototype.slic() 메서드를 마치 자신의 것 처럼 사용하게 된다.
5. 함수 리턴
- 자바 스크립트 함수는 리턴문을 사용하지 않았더라도 다음의 규칙으로 항상 리턴값을 전달한다.
- 일반 함수나 메서드는 리턴값을 지정하지 않을 경우, undefined 값이 리턴됨
- 생성자 함수에서 리턴값을 지정하지 않을 경우 생성된 객체가 리턴된다.
- 생성자 함수에서 리턴값을 지정하였더라도, 객체가 아니라면 해당 리턴값은 무시하고 this로 바인딩된 객체가 리턴된다.
'CSE > Java Script' 카테고리의 다른 글
[Java Script] 실행 컨텍스트 (0) | 2021.08.05 |
---|---|
[Java Script] 함수와 프로토타입 체이닝 4 (0) | 2021.08.05 |
[Java Script] 함수와 프로토타입 체이닝 2 (0) | 2021.08.02 |
[Java Script] 함수와 프로토타입 체이닝 1 (0) | 2021.07.30 |
[Java Script]데이터 타입과 연산자 3 (기본 타입과 표준 메서드, 연산자) (0) | 2021.07.27 |