-> 함수를 선언되었을 때가 아닌 호출되었을때 결정
-> ES5는 함수를 어떻게 호출했는지 상관하지 않고 this 값을 설정할 수 있는 bind 메서드를 도입
-> ES2015는 스스로의 this 바인딩을 제공하지 않는 화살표 함수를 추가
전역객체(Global Object)는 모든 객체의 유일한 최상위 객체를 의미한다
- Browser-side에서는 window객체
- Server-side(Node.js)에서는 global객체
function foo() {
console.log("foo's this: ", this); // window
function bar() {
console.log("bar's this: ", this); // window
}
bar();
}
foo();
👉 기본적으로 this 는 전역객체에 바인딩 되고, 내부함수의 this 도 전역객체에 바인딩 된다.
//내부함수
var value = 1;
var obj = {
value: 100,
foo: function() {
console.log("foo's this: ", this); // obj
console.log("foo's this.value: ", this.value); // 100
function bar() {
console.log("bar's this: ", this); // window
console.log("bar's this.value: ", this.value); // 1
}
bar();
}
};
obj.foo();
----------------------------------------------------
//콜백함수
var value = 1;
var obj = {
value: 100,
foo: function() {
setTimeout(function() {
console.log("callback's this: ", this); // window
console.log("callback's this.value: ", this.value); // 1
}, 100);
}
};
obj.foo();
🔥 this가 전역 객체에 바인딩 되는 경우
전역 함수에서의 this
내부 함수(중첩 함수)에서의 this
메서드의 내부 함수에서의 this
콜백 함수에서의 this
이벤트에서의 this는 '이벤트 객체'
메서드에서의 this는 '메서드 객체'
🫧 메서드 내부에서의 this
//메소드 내부 this
var obj1 = {
name: 'Lee',
sayName: function() {
console.log(this.name); //Lee
}
}
var obj2 = {
name: 'Kim'
}
obj2.sayName = obj1.sayName; //Kim
obj1.sayName();
obj2.sayName();
👉 함수가 객체의 프로퍼티 값일 시, 메소드로서 호출되고, this는 메소드를 소유한 객체가 된다.
----------------------------------------------------
//프로토타입 객체
function Person(name) {
this.name = name;
}
Person.prototype.getName = function() {
return this.name;
}
var me = new Person('Lee');
console.log(me.getName()); //Lee
Person.prototype.name = 'Kim';
console.log(Person.prototype.getName()); //Kim
👉 프로토타입 객체도 메소드를 가질 수 있고, 프로토타입 객체의 this도 해당 메소드를 호출한 객체를 바인딩한다.
어떤 함수가 생성자 함수로서 호출된 경우 내부에서의 this는 곧 새로 만들 구체적인 객체(인스턴스) 자신이다.
// 생성자 함수
function Person(name) {
// 생성자 함수 코드 실행 전 -------- 1
this.name = name; // --------- 2
// 생성된 함수 반환 -------------- 3
}
var me = new Person('Lee');
console.log(me); // Person {name: 'Lee'}
// new 연산자와 함께 생성자 함수를 호출하지 않으면 생성자 함수로 동작하지 않는다.
var you = Person('Kim');
console.log(you); // undefined
👉 new 연산자와 함께 생성자 함수를 호출하면 this 바인딩이 메소드나 함수 호출 때와는 다르게 동작한다.
// 객체 리터럴 방식
var foo = {
name: 'foo',
gender: 'male'
}
console.dir(foo); //Object
// 생성자 함수 방식
function Person(name, gender) {
this.name = name;
this.gender = gender;
}
var me = new Person('Lee', 'male');
console.dir(me); //Person
var you = new Person('Kim', 'female');
console.dir(you); //Person
/* 객체 리터럴 방식과 생성자 함수 방식의 차이는 프로토타입 객체([[Prototype]])에 있다.
객체 리터럴 방식의 경우, 생성된 객체의 프로토타입 객체는 Object.prototype이다.
생성자 함수 방식의 경우, 생성된 객체의 프로토타입 객체는 Person.prototype이다.
프로토타입이 다르므로 상위 객체가 다르다
*/
가장 큰 차이점은 재사용 가능 여부입니다. 객체 리터럴 방식으로 객체를 생성하는 방법은 재사용할 수 없지만, 생성자 함수는 재사용할 수 있습니다.
생성자 함수는 new 연산자를 붙여서 함수를 호출하면 return문이 없어도 객체가 반환된다는 점 이외에는 일반 함수와 큰 차이점이 없다. (new 연산자를 사용해야 객체가 반환된다)
function Person(name, gender) {
this.name = name;
this.gender = gender;
}
var me = Person('Lee', 'male');
console.log(me); // undefined
👉 javascript 함수에 return문이 존재하지 않을 시 함수는 undefined를 반환한다.
Function.prototype.apply, Function.prototype.call, Function.prototype.bind 메소드는 모든 함수 객체의 프로토타입 객체인 Function.prototype 객체의 메소드이다.
Person.apply(foo, [1, 2, 3]);
Person.call(foo, 1, 2, 3);```
apply() 메소드는 this를 특정 객체에 바인딩할 뿐 본질적인 기능은 함수 호출이다.
var Person = function (name) {
this.name = name;
};
var foo = {};
// apply 메소드는 생성자함수 Person을 호출, 이때 this에 객체 foo를 바인딩한다.
Person.apply(foo, ['name']);
console.log(foo); // { name: 'name' }
function Person(name) {
this.name = name;
}
Person.prototype.doSomething = function(callback) {
if(typeof callback == 'function') {
// --------- 1
callback();
}
};
function foo() {
console.log(this.name); // --------- 2
}
var p = new Person('Lee');
p.doSomething(foo); // undefined
1에서 this는 Person 객체이다.
2에서 this는 전역 객체 window를 가리킨다.
기본적으로 콜백함수 내부의 this는 window를 가리킨다
// --------- 1
callback.call(this);
콜백함수 내부의 this를 콜백함수를 호출하는 함수 내부 this와 일치시킨다.
// --------- 1
callback.bind(this)();
function Person(name) {
this.name = name;
}
Person.prototype.doSomething = function (callback) {
if (typeof callback == 'function') {
// callback.call(this);
// this가 바인딩된 새로운 함수를 호출
callback.bind(this)();
}
};
function foo() {
console.log('#', this.name);
}
var p = new Person('Lee');
p.doSomething(foo); // 'Lee'
👉 함수에 인자로 전달한 this가 바인딩된 새로운 함수를 리턴,
Function.prototype.bind는 Function.prototype.apply, Function.prototype.call 메소드와 같이 함수를 실행하지 않기 때문에 명시적으로 함수를 호출할 필요가 있다.