-
์๋ฐ์คํฌ๋ฆฝํธ๋ ํจ์ ํธ์ถ ๋ฐฉ์์ ์ํด this์ ๋ฐ์ธ๋ฉ๋๋ ๊ฐ์ฒด๊ฐ ๋์ ์ผ๋ก ๊ฒฐ์ ๋๋ค.
-
์ฆ, ํจ์๋ฅผ ํธ์ถํ ๋ ํจ์๊ฐ ์ด๋ป๊ฒ ํธ์ถ๋์๋์ง์ ๋ฐ๋ผ this๊ฐ ๋์ ์ผ๋ก ๊ฒฐ์ ๋๋ค.
-
ํจ์ ํธ์ถ ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ๋ค.
- ํจ์ ํธ์ถ
- ๋ฉ์๋ ํธ์ถ
- ์์ฑ์ ํจ์ ํธ์ถ
- apply / call / bind ํธ์ถ
const foo = function () {
console.dir(this);
};
// 1. ํจ์ ํธ์ถ
foo();
// 2. ๋ฉ์๋ ํธ์ถ
const obj = { foo: foo };
obj.foo();
// 3. ์์ฑ์ ํจ์ ํธ์ถ
const instance = new foo();
// 4. apply, call, bind ํธ์ถ
const bar = { name: "bar" };
foo.call(bar);
foo.apply(bar);
foo.bind(bar);
- ์ ์ญ ๊ฐ์ฒด(GO) ๋ ๋ชจ๋ ๊ฐ์ฒด์ ์ ์ผํ ์ต์์ ๊ฐ์ฒด์ด๋ค.
- ๋ธ๋ผ์ฐ์ ์์๋ window, ์๋ฒ์์๋ global ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
- ์ ์ญ ๊ฐ์ฒด๋ ์ ์ญ ์ค์ฝํ๋ฅผ ๊ฐ๋ ์ ์ญ ๋ณ์๋ฅผ ํ๋กํผํฐ๋ก ๊ฐ๊ณ ์๋ค. ๊ธ๋ก๋ฒ ์์ญ์์ ์ ์ธํ ํจ์๋ ์ ์ญ๊ฐ์ฒด์ ํ๋กํผํฐ๋ก ์ ๊ทผํ ์ ์๋ ์ ์ญ ๋ณ์ ๋ฉ์๋์ด๋ค.
var ga = 'Global variable';
console.log(ga); // Global variable
console.log(window.ga); // Global variable
function foo() {
console.log('invoked!');
}
window.foo(); // invoked!
-
const๋ let ํค์๋๋ก ์ ์ธ๋ ์ ์ญ ๋ณ์๋ ์ ์ญ ๊ฐ์ฒด์ ํ๋กํผํฐ๊ฐ ์๋๋ค.
```javascript=
const constVar = 'Const Global Varable';
console.log(window.constVar); // undefined
const funcTest = function(){ console.log('function invoked!'); } window.funcTest(); // VM3802:1 Uncaught TypeError: window.funcTest is not a function window.funcTest // undefined
- **๊ธฐ๋ณธ์ ์ผ๋ก this๋ ์ ์ญ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ๋๋ค.**
- **๋ด๋ถํจ์**์ ๊ฒฝ์ฐ์๋ ์ ์ญ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ๋๋ค.
```javascript
function foo() {
console.log("foo's this: ", this); // window
function bar() {
console.log("bar's this: ", this); // window
}
bar();
}
foo();
-
๋ฉ์๋์ ๋ด๋ถํจ์ ์ผ ๊ฒฝ์ฐ์๋ ์ ์ญ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ ๋๋ค.
```javascript
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();
- **์ฝ๋ฐฑ ํจ์** ์ผ ๋์๋, this๋ ์ ์ญ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ ๋๋ค.
```javascript
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๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
var value = 1;
var obj = {
value: 100,
foo: function() {
setTimeout(() => {
console.log("callback's this: ", this); // obj
console.log("callback's this.value: ", this.value); // 100
}, 100);
}
};
obj.foo();
- ๋ช
์์ ์ผ๋ก this๋ฅผ ๊ฒฐ์ ํ๋ ๋ฐฉ์์,
apply
,call
,bind
๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค.
var value = 'global value';
undefined
var obj = {
value: 'obj value',
foo: function() {
console.log("foo's this: ", this); // obj
console.log("foo's this.value: ", this.value); // obj value
function bar(a, b) {
console.log("bar's this: ", this); // obj
console.log("bar's this.value: ", this.value); // obj value
console.log("bar's arguments: ", arguments); // Arguments(2) [1, 2, callee: ฦ, Symbol(Symbol.iterator): ฦ]
}
bar.apply(obj, [1, 2]);
bar.call(obj, 1, 2);
bar.bind(obj)(1, 2);
}
};
- ํจ์๊ฐ ๊ฐ์ฒด์ ํ๋กํผํฐ์ผ ๋, ํจ์๋ฅผ ๋ฉ์๋๋ผ๊ณ ํ๋ค.
- ๋ฉ์๋ ๋ด๋ถ์ this๋ ํด๋น ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ ๋๋ค.
const bear = {
name: "bear",
sayName: function () {
console.log(this.name);
},
};
const tiger = {
name: "tiger",
};
tiger.sayName = bear.sayName;
bear.sayName(); // bear
tiger.sayName(); // tiger
- ํ๋กํ ํ์ ์ ๋ฉ์๋์ ๊ฒฝ์ฐ์๋, ํด๋น ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ๋๋ค.
function Person(name) {
this.name = name;
}
Person.prototype.getName = function () {
console.log(this);
return this.name;
};
Person.prototype.name = "Kim";
console.log(Person.prototype.getName()); // Kim
const me = new Person("Lee");
console.log(me.getName()); // Lee
- ์์ฑ์ ํจ์๋?
- ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ์ญํ
- ํ์์ด ์ ํด์ ธ์์ง ์์ผ๋ฉฐ, ๊ธฐ์กด ํจ์์
new
์ฐ์ฐ์๋ฅผ ๋ถ์ฌ์ ํธ์ถํ๋ฉด, ํด๋น ํจ์๋ ์์ฑ์ ํจ์๋ก ๋์ํ๋ค. - ์ผ๋ฐ์ ์ผ๋ก ์์ฑ์ ํจ์๋ช ์ ์ฒซ ๋ฌธ์๋ฅผ ๋๋ฌธ์๋ก ํ๊ธฐํ์ฌ, ์์ฑ์ ํจ์์์ ๋ํ๋ธ๋ค.
- new ์ฐ์ฐ์๋ก ์์ฑ์ ํจ์ ํธ์ถ ์ ๋ค์๊ณผ ๊ฐ์ ์์๋ก ๋์ํ๋ค.
- 1. ๋น ๊ฐ์ฒด ์์ฑ ๋ฐ this ๋ฐ์ธ๋ฉ
- ๋น ๊ฐ์ฒด๊ฐ ์์ฑ๋๊ณ , ์์ฑ์ ํจ์ ๋ด๋ถ์ this๋ ์ด ๋น ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
- ๊ฐ์ฒด์
__proto__
๋ ์์ ์ ํ๋กํ ํ์ ๊ฐ์ฒด๋ก ์์ฑ์ ํจ์์ prototype object๋ฅผ ๊ฐ๋ฆฌํจ๋ค. ์ด ๊ฐ์ฒด๋ ์์ฑ์ ํจ์์ prototype ํ๋กํผํฐ๊ฐ ๊ฐ๋ฆฌํค๊ณ ์๋ค.
- 2. this๋ฅผ ํตํ ํ๋กํผํฐ ์์ฑ
- ๋น ๊ฐ์ฒด์ ๋์ ์ผ๋ก ํ๋กํผํฐ๋ ๋ฉ์๋๋ฅผ ์์ฑํ๋ค. ์ด ๋, this๋ ์๋ก ์์ฑ๋ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๋ฏ๋ก, this๋ฅผ ํตํด ์์ฑํ ํ๋กํผํฐ์ ๋ฉ์๋๋ ์๋ก ์์ฑ๋ ๊ฐ์ฒด์ ์ถ๊ฐ๋๋ค.
- 3. ์์ฑ๋ ๊ฐ์ฒด ๋ฐํ
-
๋ฐํ๋ฌธ์ด ์๋ ๊ฒฝ์ฐ, this์ ๋ฐ์ธ๋ฉ๋ ์๋ก ์์ฑํ ๊ฐ์ฒด๊ฐ ๋ฐํ๋๋ค. ๋ช ์์ ์ผ๋ก this๋ฅผ ๋ฐํํ ๊ฒ๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ์ด๋ค.
function Food(name) { this.name = name; return this; // ๋ช ์์ ์ผ๋ก this๋ฅผ ๋ฐํํ์ง ์์๋, ์๋ก ์์ฑ๋ ๊ฐ์ฒด๊ฐ ๋ฐํ๋๋ค. } const apple = new Food("apple"); console.log(apple.name); // apple
-
๋ฐํ๋ฌธ์ด this๊ฐ ์๋ ๋ค๋ฅธ ๊ฐ์ฒด๋ฅผ ๋ช ์์ ์ผ๋ก ๋ฐํํ๋ค๋ฉด, this๊ฐ ์๋ ํด๋น ๊ฐ์ฒด๊ฐ ๋ฐํ๋๋ค. ํด๋น ํจ์๋ ์์ฑ์ ํจ์๋ก์์ ์ญํ ์ ์ํํ์ง ๋ชปํ๋ค.
const lemon = { name: "lemon" }; function Food(name) { this.name = name; return lemon; } const apple = new Food("apple"); console.log(apple.name); // lemon;
-
- 1. ๋น ๊ฐ์ฒด ์์ฑ ๋ฐ this ๋ฐ์ธ๋ฉ
- ์์ฑ๋ ๊ฐ์ฒด์ ํ๋กํ ํ์
๊ฐ์ฒด
-
๊ฐ์ฒด ๋ฆฌํฐ๋ด ๋ฐฉ์ : Object.prototype
-
์์ฑ์ ํจ์ ๋ฐฉ์ : ์์ฑ์ ํจ์์ prototype์ด ๊ฐ๋ฆฌํค๋ ๊ฐ์ฒด, ์ฆ Person.prototype
```javascript
// ๊ฐ์ฒด ๋ฆฌํฐ๋ด ๋ฐฉ์
var foo = {
name: 'foo',
gender: 'male'
}
-
console.dir(foo);
// Object // gender: "male" // name: "foo" // proto: Object
// ์์ฑ์ ํจ์ ๋ฐฉ์ function Person(name, gender) { this.name = name; this.gender = gender; }
var me = new Person('Lee', 'male'); console.dir(me);
// Person // gender: "male" // name: "Lee" // proto: Object
### ์์ฑ์ ํจ์์ new๋ฅผ ๋ถ์ด์ง ์๊ณ ํธ์ถํ ๊ฒฝ์ฐ
์์ฑ์ ํจ์์ new๋ฅผ ๋ถ์ด์ง ์๊ณ ํธ์ถํ ๊ฒฝ์ฐ, ์ผ๋ฐ ํจ์๋ฅผ ํธ์ถํ ๊ฒ์ด๊ธฐ์, this๋ฅผ ๋ฐํํ์ง ์๋๋ค. ์ด ๋ ํจ์ ๋ด์ this๋ ์ ์ญ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ๋๋ค.
```javascript
function Seat(number) {
this.number = number;
}
// new ํค์๋ ์์ด ํธ์ถํ ๊ฒฝ์ฐ, this๋ ์ ์ญ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ๋๋ค.
// ๋ํ, ๋ฐํ๋ฌธ์ด ์์ผ๋ฏ๋ก undefined๋ฅผ ๋ฐํํ๊ฒ ๋๋ค.
const myseat = Seat(1);
console.log(myseat); // undefined
console.log(window.number); // 1
์ด์ฒ๋ผ ์์ฑ์ ํจ์๋ฅผ new ํค์๋ ์์ด ํธ์ถํ๊ฒ ๋๋ฉด, new ํค์๋๋ก ์์ฑํ ๊ฒ๊ณผ ๋ค๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ์ด๋ํ๋ค. ๋ฐ๋ผ์ ๊ทธ๋ฌํ ์ค์๋ฅผ ๋ฐฉ์งํ๊ณ ์ Scope-Safe Constructor๋ก ์์ฑ์ ํจ์๋ฅผ ๋ง๋ค๊ฒ ๋๋ค. ์ด ํจํด์ ๋๋ถ๋ถ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ๊ด๋ฒ์ํ๊ฒ ์ฌ์ฉ๋๋ค.
function Ssc(arg) {
if (!(this instanceof arguments.callee)) {
return new arguments.callee(arg);
}
this.value = arg ? arg : 0;
}
const ssc1 = new Ssc(10);
const ssc2 = Ssc(30);
console.log(ssc1.value); // 10
console.log(ssc2.value); // 30
arguments.callee๋ ํจ์ ๋ฐ๋ ๋ด์์ ํ์ฌ ์คํ์ค์ธ ํจ์์ ์ด๋ฆ์ด๋ค. this๊ฐ ํ์ฌ ํธ์ถ๋ ํจ์์ ์ธ์คํด์ค๊ฐ ์๋๋ผ๋ฉด, new ํค์๋ ์์ด ํธ์ถ๋ ํจ์์ด๋ค. ๋ฐ๋ผ์ new ํค์๋์ ํจ๊ป ์์ฑ์ ํจ์๋ฅผ ํธ์ถํ์ฌ, ์๋ก์ด ๊ฐ์ฒด์ this๊ฐ ๋ฐ์ธ๋ฉ๋ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋๋ก ํ๋ค.
- ๊ธฐ๋ณธ์ ์ผ๋ก this๋ ํจ์ ํธ์ถ ํจํด์ ๋ฐ๋ผ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ์ํด this๊ฐ ๋ฐ์ธ๋ฉ๋๋ค.
- ๋ช ์์ ์ผ๋ก this๋ฅผ ํน์ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉํ๋ ค๋ฉด, Function.prototype.apply, Function.prototype.call, Function.prototype.bind ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
func.apply(thisArg, [argsArray]) func.call(thisArg[, arg1[, arg2[, ...]]])
- apply์ call์ this๋ฅผ ํน์ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉํ ๋ฟ, ๋ณธ์ง์ ์ธ ๊ธฐ๋ฅ์ ํจ์ ํธ์ถ์ด๋ค.
func.bind(thisArg[, arg1[, arg2[, ...]]])
- bind ๋ฉ์๋๋ ์ธ์๋ก ๋ฐ์ this๊ฐ ๋ฐ์ธ๋๋ ํจ์๋ฅผ ๋ฆฌํดํ๋ค. ๋ฐ๋ผ์, ํจ์ ํธ์ถ์ ๋ฐ๋ก ํด์ฃผ์ด์ผ ํ๋ค.
function Product(name) {
this.name = name;
}
const mouse = {};
const monitor = {};
const keyboard = {};
Product.call(mouse, "mouse");
Product.apply(monitor, ["monitor"]);
Product.bind(keyboard)("keyboard");
console.log(mouse); // { name: 'mouse' }
console.log(monitor); // { name: 'monitor' }
console.log(keyboard); // { name: 'keyboard' }
function Relation(relation) {
this.relation = relation;
}
Relation.prototype.func = function (callback) {
if (typeof callback === "function") {
// (A)
callback(); // undefined
}
};
const brother = new Relation("brother");
function log() {
// (B)
console.log(this.relation);
}
brother.func(log);
(A)๋ ํ๋กํ ํ์ ๋ฉ์๋ ๋ด๋ถ์ด๋ฏ๋ก this๊ฐ ํด๋น ๋ฉ์๋๋ฅผ ํธ์ถํ ์ธ์คํด์ค์ด์ง๋ง, (B)๋ ์ผ๋ฐํจ์์ด๋ฏ๋ก (B)์์์ this๋ ์ ์ญ ๊ฐ์ฒด์ด๋ค. ์ ์ญ ๊ฐ์ฒด์ relation์ ์์ผ๋ฏ๋ก, undefined๋ฅผ ๋ฐํํ๊ฒ ๋๋ค.
์ด๋ ๊ฒ ์ฝ๋ฐฑ ํจ์์ this์ ์ฝ๋ฐฑํจ์๋ฅผ ํธ์ถํ ํจ์์ this๋ฅผ ๋ฐ์ธ๋ฉ ์์ผ์ฃผ์ด์ ์๋ํ๋๋ก ๋์ํ ์ ์๋๋ก ํ๋ค.
function Relation(relation) {
this.relation = relation;
}
Relation.prototype.func = function (callback) {
if (typeof callback === "function") {
callback.bind(this)(); // brother
}
};
const brother = new Relation("brother");
function log() {
console.log(this.relation);
}
brother.func(log);