자바스크립트에서 this
키워드는 항상 함수 내부에서 사용된다. this
값은 this
가 사용된 함수가 어떤 방식으로 실행 되었는지에 따라 결정된다.
var name = "킹스맨";
var hth = {
name: "하태현",
logName: function () {
console.log(this.name);
}
};
var func = hth.logName;
hth.logName(); // "하태현"
func(); // "킹스맨"
함수 선언시에는 this
값을 판별할 수 없다.
this
값을 알기 위해선 함수 실행문을 찾고, 어떻게 실행되었는지만 알면 this
값을 판별할 수 없다.
위 4가지 실행방법에 따라 this
값이 판별된다.
this는 함수가 "어떻게" 실행되느냐에 따라 결정되기 때문에 함수 실행 방식이 중요하다.
var name = "킹스맨"; function log () { console.log(this.name); } func(); // "킹스맨"
func()
와 같이 함수이름 만으로 실행하는 경우 일반함수 호출이라고 한다.
일반 함수 호출 방식에서 this
값은 Global Object(브라우저에선 window
객체)
var name = "킹스맨"; var hth = { name: "하태현", logName: function () { console.log(this.name); } }; var func = hth.logName; func(); // "킹스맨"
this
가 사용된 함수는hth
라는 객체의logName
이라는 속성으로 할당되어있다.
그러나 함수의 선언이나 할당은this
값과 무관하다.
위 예제 코드에서는 함수 실행 부분이func()
로 일반 함수 호출 방식으로 실행되었기 때문에this
값은 Global Object이다.
var name = "킹스맨"; function foo () { var name = "하태현"; bar(); } function bar () { console.log(this.name); } foo(); // "킹스맨"
bar
함수에서this
가 사용되었고bar
는foo
함수 내부에서 일반 함수 호출 방식으로 실행되어서 이때this
값은 Global Object이다.
var name = "킹스맨"; var hth = { name: "하태현", printName: function () { foo(); } }; function foo () { console.log(this.name); } hth.printName(); // "킹스맨"
printName
은 Dot Notation을 이용해 실행되었지만this
가 사용된foo
는 일반 함수 호출 방식으로 실행되어this
는 Global Object이다.
var name = "킹스맨"; var hth = { name: "하태현", logName: function () { console.log(this.name); } }; var func = hth.logName; // Dot Notation hth.logName(); // Regulat Function Call func();
여기서
hth.logName()
와func()
는 같은 함수를 실행한다. 그러나 실행방식의 차이로this
값이 달라진다.
Dot Notation을 이용해 함수를 실행하면, 해당함수 내부의this
는 Dot 앞의 객체를 가리킨다.hth.logName()
에서this
는hth
객체를 가리킨다.
var age = 20; function logAge () { console.log(this.age); } var hth = { age: 28, logAge: logAge }; var htg = { age: 26, logAge: hth.logAge }; hth.logAge(); // 28 htg.logAge(); // 26 console.log(hth.logAge); console.log(htg.logAge);
console.log
의 결과를 보면 둘다 같은 함수를 가리킨다. 결국hth.logAge()
,htg.logAge()
를 실행하면this
값은 Dot앞의 객체인hth
와htg
를 가리키게 되어 결과 값이 28, 26이 나온다.
function makePerson(name, age) { return { name: name, age: age, verifyAge: () => { return this.age > 21; } }; } const hth = makePerson("hth", 28); if(hth.verifyAge()){ console.log("Yes Beer"); } else { console.log("No Beer"); }
결과는 "No Beer"가 나온다.
예상대로라면 28살이기 때문에 "Yes Beer"가 나와야 하는데...
verifyAge
를 자세히 보면 화살표 함수가 쓰였다.
찾아보니 일반함수의 this값은 동적으로 결정 되는데, 화살표 함수는 항상 상위 스코프의 this값을 가리키게 되어있다고 한다.
그래서hth.verifyAge()
를 실행하면hth
객체의 상위 스코프인 Global Object가this
값으로 결정되어this.age
는undefined
가 된다.
우선 자바스크립트의 객체(배열, 함수)는 내장된 메소드를 가지고 있다. 여기서 설명할 함수 실행 방식은 함수(function
)가 갖고 있는 특정 메소드를 이용한 방법이다.
Call, Apply, Bind는 명시적 바인딩을 할때 사용하는 함수이다.
어떤 함수안에서 사용되는 this의 값이 어떤 값이 사용되야하는지 명확할때 사용하는 방식
Function.prototyope.call
모든 함수는
.call
메소드를 사용할수 있다.function logName () { console.log(this.name); } const person = { name: "하태현", }; // call 메소드를 이용한 함수 실행 logName.call(person); // "하태현"
call
메소드의 역할은logName
함수의this
값을person
으로 설정한다.logName
함수를 실행(logName()
으로 실행하는 것과 같은 의미)function foo (a, b, c) { console.log(this.age + a + b + c); } const hth = { age: 28, }; foo.call(hth, 1, 2, 3); // 34
.call
메소드의 첫번째 인자는this
값으로 사용되고, 두번째 인자부터 해당함수의 인자로 사용된다.
.call
메소드는 받을 수 있는 인자 개수는 제한이 없다.
Function.prototyope.apply
function foo (a, b, c) { console.log(this.age, a + b + c); } const hth = { age: 28, }; foo.apply(hth, [1, 2, 3]); // 34
.call
메소드와 다른게 뭘까??
.apply
메소드는 2개의 인자만을 받는다.
첫번째 인자는this
값으로 사용되고, 두번째 인자는 무조건 배열 이여야 하고 그 배열의 요소들이 함수의 인자로 전달된다.
.call
과 .apply
공통점
this
값으로 설정차이점
call
: 첫번째 인자를 제외한 나머지를 모두 .call
이 사용된 함수의 인자로 전달(인자 개수 제한 없음)apply
: 두번째 인자로 배열을 받을수 있고, 해당 배열의 모든 요소들을 함수의 인자로 전달(2개의 인자만 받는다)
Function.prototyope.bind
function foo () { console.log("hello"); } // bar 변수에는 새로운 함수가 담긴다. const bar = foo.bind(); bar();
.bind
메소드는 함수를 실행하지 않고 새로운 함수를 반환한다.function logName () { console.log(this.name); } const person = { name: "하태현", }; const bar = foo.bind(hth); bar(); // "하태현"
bar
는this
값을hth
로 설정한foo
함수이다.function foo (a, b, c) { console.log(this.age + a + b + c); } const hth = { age: 28, }; const bar = foo.bind(hth, 1, 2, 3); bar(); // 34
bind
메소드는call
메소드와 유사하게 인자 개수에 제한이 없고, 위 예제 코드에서는this
값과 인자값을 저장한 새로운 함수를 만든다.
bind
메소드는 새로운 함수를 반환하고, 그 함수를 실행해야 원본 함수가 실행된다.
Keyword(키워드)는 자바스크립트에 내장된 명령어이다.
function foo () { console.log("function"); } new foo();
기본적으로
new
키워드와 함께 함수를 실행하면 일반 함수 실행문과 동일한 작동을 한다.
function foo () { console.log(this); } new foo(); // 빈 객체 출력
function Person (name) { this.name = name; console.log(this); } new Person("hth");
필요한 경우 새로운 속성을 추가 할수 있다.
new
키워드와 함께 사용될 경우 해당 함수를 생성자 함수라고 부른다.
function Person (name) { this.name = name; console.log(this); } Person("hth"); // 일반함수로 사용 new Person("hth"); // 생성자 함수로 사용
보통 일반 함수 용도로 만든 함수는 일반함수로만 사용하고, 생성자함수 용도로 만든 함수는 생성자 함수로만 사용한다.
function Person (name, age) { this.name = name; this.age = age; } new Person("hth", 28);
생성자 함수는 통상적으로 함수명을 대문자로 시작한다.