JS에서 this는 정적으로 할당 되지 않고, 동적으로 할당된다.
이 말을 쉽게 해석하자면 this가 선언되었을 때가 아닌, 호출되었을 때 결정된다는 의미이다.
예)
const person = function (name) {
this.name = name; // 이때 this는 결정되지 않는다.
}
const person1 = new person('park'); // 이 때 결정 된다.
console.log(person1.name); // park
예1)
function foo() {
console.log("foo's this: ", this); // window
function bar() {
console.log("bar's this: ", this); // window
}
bar();
}
foo();
예2)
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();
예3)
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도 해당 메소드를 호출한 객체를 바인딩한다.
예)
var obj1 = {
name: 'Lee',
sayName: function() {
console.log(this.name);
}
}
var obj2 = {
name: 'Kim'
}
obj2.sayName = obj1.sayName;
obj1.sayName(); // /Lee
obj2.sayName(); // kim
예2)
function Person(name) {
this.name = name;
}
Person.prototype.getName = function() {
return this.name;
}
var me = new Person('Lee');
console.log(me.getName());
Person.prototype.name = 'Kim';
console.log(Person.prototype.getName());
JS에서 함수는 값으로 역할을 하고, new 키워드를 통해, 일반함수를 생성자 함수로 사용할 수 있다.
// 생성자 함수
function Person(name) {
this.name = name;
}
var me = new Person('Lee');
console.log(me); // Person {name: "Lee"}
// new 연산자와 함께 생성자 함수를 호출하지 않으면 생성자 함수로 동작하지 않는다.
var you = Person('Kim');
console.log(you); // undefined
function Person(name) {
// 생성자 함수 코드 실행 전 -------- 1번
this.name = name; // --------- 2번
// 생성된 함수 반환 -------------- 3번
}
var me = new Person('Lee');
console.log(me.name);
const object = {
name: "park",
age: 12,
} // 객체 리터럴방식
const Person = function (name, age) {
this.name = name;
this.age = age;
} // 생성자 함수 선언
const person1 = new Person("Lee", 13); // 생성자 함수 방식
위 객체 리터럴 방식과 생성자 함수 방식의 차이는 생성자 함수의 prototype 객체는 Object이고,
객체리터럴방식의 prototype 객체는 Person이다.
대부분의 new 없이 사용하는 빌트인 생성자(Array, Regex..)는 scope-safe Constructor Pattern을 사용한다. 아래는 scope-safe Constructor Pattern 의 예제이다
function A(arg) {
// arguments.callee는 호출된 함수의 이름을 나타낸다.
if(!(this instanceof arguments.callee)) {
return new arguments.callee(arg);
}
this.value = arg ? arg : 0;
}
var a = new A(100);
var b = A(100);
console.log(a.value);
console.log(b.value);
callee는 arguments 객체의 프로퍼티로서 함수 바디 내에서 현재 실행 중인 함수를 참조할 때 사용한다. 다시 말해, 함수 바디 내에서 현재 실행 중인 함수의 이름을 반환한다.
apply/call/bind 이 함수들은 명시적으로 어떤 객체에 바인딩 할 수 있는 메소드들이다.
Function.prototype.apply, Function.prototype.call 이다.
func.apply(thisArgs, [argsArray]);
func.call(thisArgs, argument1, argument2...)
func.bind(thisArgs)();
감사합니다