๐ ๋ชจ๋ ์๋ฐ์คํฌ๋ฆฝํธ Deep dive - ์ด์ ๋ชจ ์ค ์ผ๋ถ๋ฅผ ๊ฐ์ ธ์์ ์ค์ ํฌ์ธํธ๋ฅผ ํ์ํ๊ณ ์ดํดํ๋ฉฐ ๊ธฐ๋กํ์์ต๋๋ค.
๐ ์์ ์ this์ ๊ดํด ์ผ๋ ๊ธ
ย ย ์๋ฐ์คํฌ๋ฆฝํธ์ ํจ์๋ ํธ์ถ๋ ๋, ๋งค๊ฐ๋ณ์๋ก ์ ๋ฌ๋๋ ์ธ์๊ฐ ์ด์ธ์, arguments ๊ฐ์ฒด์ this ๋ฅผ ์๋ฌต์ ์ผ๋ก ์ ๋ฌ๋ฐ์ต๋๋ค.
1. ์ ๋ฌ์ธ์ ๊ฐ 2. arguments(์ ๋ฌ์ธ์) ๊ฐ์ฒด 3. this ๊ฐ์ฒด
function square(number) {
console.log(arguments);
console.log(this);
return number * number;
}
square(2);
์๋ฐ์คํฌ๋ฆฝํธ์ this keyword๋ Java์ ์ต์ํ ์ธ์ด์ ๊ฐ๋
๊ณผ ๋ฌ๋ผ ๊ฐ๋ฐ์์๊ฒ ํผ๋์ ์ค๋๋ค. Java์์์ this๋ ์ธ์คํด์ค ์์ (self)์ ๊ฐ๋ฆฌํค๋ ์ฐธ์กฐ๋ณ์์
๋๋ค. this๊ฐ ๊ฐ์ฒด ์์ ์ ๋ํ ์ฐธ์กฐ ๊ฐ์ ๊ฐ์ง๊ณ ์๋ค๋ ๋ป์
๋๋ค. ์ฃผ๋ก ๋งค๊ฐ๋ณ์์ ๊ฐ์ฒด ์์ ์ด ๊ฐ์ง๊ณ ์๋ ๋ฉค๋ฒ ๋ณ์๋ช
์ด ๊ฐ์ ๊ฒฝ์ฐ ์ด๋ฅผ ๊ตฌ๋ถํ๊ธฐ ์ํด์ ์ฌ์ฉ๋ฉ๋๋ค.
ย ย ์๋ Java ์ฝ๋์ ์์ฑ์ ํจ์ ๋ด์ this.name์ ๋ฉค๋ฒ๋ณ์๋ฅผ ์๋ฏธํ๋ฉฐ name์ ์์ฑ์ ํจ์๊ฐ ์ ๋ฌ๋ฐ์ ๋งค๊ฐ๋ณ์๋ฅผ ์๋ฏธํฉ๋๋ค.
public Class Person {
private String name;
public Person(String name){
this.name = name;
}
}
ํ์ง๋ง ์๋ฐ์คํฌ๋ฆฝํธ์ ๊ฒฝ์ฐ Java์ ๊ฐ์ด this์ ๋ฐ์ธ๋ฉ ๋๋ ๊ฐ์ฒด๋ ํ ๊ฐ์ง๊ฐ ์๋๋ผ ํด๋น ํจ์ ํธ์ถ ๋ฐฉ์์ ๋ฐ๋ผ this์ ๋ฐ์ธ๋ฉ ๋๋ ๊ฐ์ฒด๊ฐ ๋ฌ๋ผ์ง๋๋ค.
1. ๊ฐ์ฒด ๋ด๋ถ ์ผ๋ฐ property์ this
ย ย ๋ฉ์๋ ํ์์ this๊ฐ ์๋๋ผ ์ผ๋ฐ ํ๋กํผํฐ์ ๋ถ์ฌ๋ this์ ๊ฒฝ์ฐ์๋ global this๋ฅผ ๊ฐ๋ฆฌํต๋๋ค.

ย ย depth(๊น์ด)์ ์๊ด์์ด global this ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ๋ฉ๋๋ค.
๋ธ๋ผ์ฐ์ ํ๊ฒฝ์์๋ global ๊ฐ์ฒด์ธ window ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ๋๊ฒ ๋ค์.
/**
ย * # `Browser`ํ๊ฒฝ์์ this ๊ฐ์ฒด
ย */
var foo = 40;
const depthCheck1 = {
ย foo: 30,
ย // .์ฐ์ฐ์๊ฐ depthCheck1๋ฅผ ๊ฐ๋ฆฌํค์ง๋ง ๋ฉ์๋๊ฐ ์๋๋ฏ๋ก global this ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
ย tool1: this.foo,
};
console.log(depthCheck1.tool1); // 40
const depthCheck2 = {
ย foo: 30,
ย tool1: {
ย ย // .์ฐ์ฐ์๊ฐ depthCheck2.tool1๋ฅผ ๊ฐ๋ฆฌํค์ง๋ง ๋ฉ์๋๊ฐ ์๋๋ฏ๋ก global this ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
ย ย result: this.foo,
ย },
};
console.log(depthCheck2.tool1.result); // 40
(๋ฉ์๋๋ ๋ฐ์์ ์์ธํ๊ฒ ๋ค๋ฃน๋๋ค. ์ฌ๊ธฐ์๋ ๊ทธ๋ฅ ๊ทธ๋ ๊ตฌ๋ ํ๊ณ ๋์ด๊ฐ์๋ค.)
๋ฉ์๋ ํ์ ๊ฐ์ฒด ํ๋กํผํฐ์ this ๊ฐ์ฒด๋ ํธ์ถ๋ ๋ฉ์๋์ ์ .์ฐ์ฐ์๊ฐ ์ฐธ์กฐํ๊ณ ์๋ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํต๋๋ค.
const depthCheck3 = {
ย foo: 30,
ย tool1: {
ย ย foo: 40,
ย ย result1: function () {
ย ย ย console.log(this.foo);
ย ย ย function bar() {
ย ย ย ย console.log(this);
ย ย ย }
ย ย ย bar();
ย ย ย const innerMethod = {
ย ย ย ย /**
ย ย ย ย ย * * innerMethod ๊ฐ์ฒด ์์ ์คํ ๋ฌธ๋งฅ์ด result1 `๋ฉ์๋`์ด๋ฏ๋ก this ๊ฐ์ฒด๊ฐ ์ ํจํ๋ค.
ย ย ย ย ย * IM: this.foo, // 40 ๊ฐ์ผ๋ก ๊ฐ์ง๋ค.
ย ย ย ย ย */
ย ย ย ย IM: this.foo, // 40
ย ย ย ย getContext: function () {
ย ย ย ย ย return this; // { IM: 40, getContext: [Function: getContext] }
ย ย ย ย },
ย ย ย };
ย ย ย console.log(`innerMethod.IM >>> ${innerMethod.IM}`); // innerMethod.IM >>> 40
ย ย ย console.log(innerMethod.getContext()); // { IM: 40, getContext: [Function: getContext] }
ย ย ย },
}
2. ํจ์ ํธ์ถ ๋ฐฉ์๊ณผ this ๋ฐ์ธ๋ฉ
ย ย ์๋ฐ์คํฌ๋ฆฝํธ์ ๊ฒฝ์ฐ ํจ์ ํธ์ถ ๋ฐฉ์์ ์ํด this ๋ฐ์ธ๋ฉํ ์ด๋ค ๊ฐ์ฒด๊ฐ ๋์ ์ผ๋ก ๊ฒฐ์ ๋ฉ๋๋ค. ๋ค์ ๋งํด, ํจ์๋ฅผ ์ ์ธํ ๋ this์ ๋ฐ์ธ๋ฉํ ๊ฐ์ฒด๊ฐ ์ ์ ์ผ๋ก ๊ฒฐ์ ๋๋ ๊ฒ์ด ์๋๊ณ , ํจ์๋ฅผ ํธ์ถํ ๋ ํจ์๊ฐ ์ด๋ป๊ฒ ํธ์ถ๋์๋์ง์ ๋ฐ๋ผ this์ ๋ฐ์ธ๋ฉํ ๊ฐ์ฒด๊ฐ ๋์ ์ผ๋ก ๊ฒฐ์ ๋ฉ๋๋ค.
ํจ์์ ์์ ์ค์ฝํ๋ฅผ ๊ฒฐ์ ํ๋ ๋ฐฉ์์ธ ๋ ์์ปฌ ์ค์ฝํ๋ ํจ์๋ฅผ ์ ์ธํ ๋ ๊ฒฐ์ ๋ฉ๋๋ค. this ๋ฐ์ธ๋ฉ๊ณผ ํผ๋ํ์ง ์๋๋ก ์ฃผ์ํด์ผ ํฉ๋๋ค.
| ์ข ๋ฅ | ํน์ง |
|---|---|
| ๋ ์์ปฌ ์ค์ฝํ | ํจ์ ์ ์ธ๋ถ์์ ๊ฒฐ์ |
| this ๊ฐ์ฒด | ํจ์ ํธ์ถ ๋ฐฉ์์ ๋ฐ๋ผ ๊ฒฐ์ |
ํจ์์ ํธ์ถํ๋ ๋ฐฉ์์ ์๋์ ๊ฐ์ด ๋ค์ํฉ๋๋ค.
1. ํจ์ ํธ์ถ 2. ๋ฉ์๋ ํธ์ถ 3. ์์ฑ์ ํจ์ ํธ์ถ 4. apply/call/bind ํธ์ถ
var foo = function () {
ย console.dir(this);
};
// 1. ํจ์ ํธ์ถ
foo(); // window
// window.foo();
// 2. ๋ฉ์๋ ํธ์ถ
var obj = { foo: foo };
obj.foo(); // obj
// 3. ์์ฑ์ ํจ์ ํธ์ถ
var instance = new foo(); // instance
// 4. apply/call/bind ํธ์ถ
var bar = { name: "bar" };
foo.call(bar); // bar
foo.apply(bar); // bar
foo.bind(bar)(); // bar
3. ํจ์ ํธ์ถ(feat. โuse strictโ ์๊ฒฉ ๋ชจ๋)
ย ย ์ ์ญ ๊ฐ์ฒด(Global Object)๋ ๋ชจ๋ ๊ฐ์ฒด์ ์ ์ผํ ์ต์์ ๊ฐ์ฒด๋ฅผ ์๋ฏธํ๋ฉฐ ์ผ๋ฐ์ ์ผ๋ก Browser-side์์๋ window , Server-side(Node.js)์์๋ global ๊ฐ์ฒด๋ฅผ ์๋ฏธํฉ๋๋ค.
// in browser console
this === window // true
// in Terminal
node
this === global // true
[์ถ๊ฐ์ ์ธ ๋ด์ฉ]
ย ย ์ข ๋ ์ ํํ ๋งํ์๋ฉด, ๋ธ๋ผ์ฐ์ ํ๊ฒฝ์์๋ ๋น์๊ฒฉ๋ชจ๋ ์ผ ๋๋ window ์ ์ญ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ์ด ๋๊ณ , ์๊ฒฉ๋ชจ๋ ์์๋ ๋ฐ์ธ๋ฉํ ๊ฐ์ฒด๊ฐ ์ฌ๋ผ์ ธ์ undefined ๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
ย ย ํํธ node ํ๊ฒฝ์์๋ global ์ด๋ผ๋ ์ ์ญ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ์ด ๋๋๋ฐ, ํจ์ ์ฝ๋ ์์์๊ฐ ์๋๋ผ ์ ์ญ ์ฝ๋์์์ this๋ฅผ ์ฝ์์ ์ถ๋ ฅํด๋ณด๋ฉด ๋น ๊ฐ์ฒด๊ฐ ๋์ต๋๋ค. ์ด ๋ ์ด ๋น ๊ฐ์ฒด๋ ์ฌ์ค ๋ชจ๋ ๊ฐ์ฒด์ ์๋ exports ๊ฐ์ฒด์ ์๋ฒฝํ๊ฒ ๋์ผํ ๊ฐ์ฒด์
๋๋ค.
/* ์ด exports ๊ตฌ๋ฌธ์ด ๋ด๋ณด๋ด๋ exports ๊ฐ์ฒด๊ฐ ์ฌ์ค node ํ๊ฒฝ ์ ์ญ ๊ฐ์ฒด๋ ์๋ฒฝํ๊ฒ ๋์ผํ ๊ฐ์ฒด์ */
module.exports = {
something: something
}
console.log(this); // {}
console.log(this === module.exports); // true
function something() {
console.log(this); // <ref *1> Object [global]
console.log(this === global); // true
}
something();
const ob = {};
const ob2 = {};
console.log(ob === ob2); // false
์ด๋ฅผ ํตํด์ node.js ํ๊ฒฝ์์ this๊ฐ 2๊ฐ์ง ๋ฐฉํฅ์ผ๋ก ๋ฐ์ธ๋ฉ์ ํ๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
ย ย ์ ์ญ ๊ฐ์ฒด๋ ์ ์ญ ์ค์ฝํ(global scope)๋ฅผ ๊ฐ๋ ์ ์ญ๋ณ์(global variable)๋ฅผ ํ๋กํผํฐ๋ก ์์ ํฉ๋๋ค. ๊ธ๋ก๋ฒ ์์ญ์ ์ ์ธํ ํจ์๋ ์ ์ญ๊ฐ์ฒด์ ํ๋กํผํฐ๋ก ์ ๊ทผํ ์ ์๋ ์ ์ญ ๋ณ์์ ๋ฉ์๋์ ๋๋ค.
var ga = 'Global variable';
/* ์๋์ ์ง๊ฟ๋ค์ ๋์ผํ ๊ฒฐ๊ณผ๋ฅผ ๋
๋๋ค. */
console.log(ga);
console.log(window.ga);
/* ์๋์ ์ง๊ฟ๋ค์ ๋์ผํ ๊ฒฐ๊ณผ๋ฅผ ๋
๋๋ค. */
function foo() {
console.log('invoked!');
}
foo();
window.foo();
๊ธฐ๋ณธ ๋ฐ์ธ๋ฉ
๊ธฐ๋ณธ์ ์ผ๋ก this๋ ์ ์ญ๊ฐ์ฒด(Global object)์ ๋ฐ์ธ๋ฉ ๋ฉ๋๋ค. ์ ์ญํจ์๋ ๋ฌผ๋ก ์ด๊ณ ์ฌ์ง์ด ๋ด๋ถํจ์์ ๊ฒฝ์ฐ๋ this๋ ์ธ๋ถํจ์๊ฐ ์๋ ์ ์ญ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ๋ฉ๋๋ค.
์ด๋ฅผ ๊ธฐ๋ณธ ๋ฐ์ธ๋ฉ์ด๋ผ๊ณ ํฉ๋๋ค.
/* ์ ์ญํจ์ ์์*/
function func() {
console.log(this); // browser ํ๊ฒฝ์์๋ window๋ฅผ ๋ก๊ทธ์ ์ฐ๋๋ค.
}
/* ์ ์ญํจ์ ๋ด๋ถํจ์ ์์ */
function foo() {
console.log("foo's this: ", this); // window
function bar() {
console.log("bar's this: ", this); // window
}
bar();
}
foo();
๋ํ ๋ฉ์๋์ ๋ด๋ถํจ์์ผ ๊ฒฝ์ฐ์๋ 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();
์ฝ๋ฐฑํจ์์ ๊ฒฝ์ฐ์๋ this๋ ์ ์ญ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ๋ฉ๋๋ค.
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๊ฐ ์ ์ญ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๋ ๊ฒ์ ํํผํ๋ ๋ฐฉ๋ฒ์ ์๋์ ๊ฐ์ต๋๋ค.
foo ๋ฉ์๋์ this ๊ฐ์ฒด๋ฅผ that์ ํ ๋นํ์ฌ bar ํจ์์ Lexical Scope ๋ฒ์๋ฅผ ์ด์ฉํ์์ต๋๋ค. bar ํจ์๋ ํธ์ถ๋์์ ๋ ์์ ์ ์ ์ธ๋ถ์ LE(Lexical Environment)์์ outerํ๊ฒฝ(outerEnvironmentReference), ์ค์ฌ์ outer๋ผ๊ณ ๋ถ๋ฆ)์ ์ฐธ์กฐํ์ฌ that์ ์ฐธ์กฐํ ์ ์๋ ๊ฒ์ด์ฃ .
var value = 1;
var obj = {
value: 100,
foo: function() {
/* 1 depth๊น์ง๋ . ์ฐ์ฐ์ ์์ obj๋ฅผ ์ฐธ์กฐํจ */
var that = this; // Workaround : this === obj
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
console.log("bar's that: ", that); // obj
console.log("bar's that.value: ", that.value); // 100
}
bar();
}
};
obj.foo();
๋ช ์์ ๋ฐ์ธ๋ฉ(apply, call, bind) ๊ทธ๋ฆฌ๊ณ Array.from์ ๋ฑ์ฅ
ย ย ์ ๋ฐฉ๋ฒ ์ด์ธ์๋ ์๋ฐ์คํฌ๋ฆฝํธ๋ this๋ฅผ ๋ช
์์ ์ผ๋ก ๋ฐ์ธ๋ฉ ํ ์ ์๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. apply, call, bind๋ฅผ ์ฌ์ฉํ์ฌ ๋ช
์์ ๋ฐ์ธ๋ฉ์ ํ ์ ์์ต๋๋ค.
์ด ๋ฉ์๋๋ค์ ๋ชจ๋ ํจ์ ๊ฐ์ฒด์ ํ๋กํ ํ์
๊ฐ์ฒด์ธ Function.prototype ๊ฐ์ฒด์ ๋ฉ์๋์
๋๋ค.
- apply, call๊ณผ ๊ด๋ จํ์ฌ ๊ธฐ์ตํด์ผ ํ ๊ฒ์ ์ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ์ฃผ์ฒด๋ ํจ์๋ผ๋ ์ ์ ๋๋ค. this๋ฅผ ํน์ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ ํ ๋ฟ ๋ณธ์ง์ ์ธ ๊ธฐ๋ฅ์ ํจ์ ํธ์ถ์ด๋ผ๋ ๊ฒ์ ๋๋ค.
- bind๋ ๋ง์ฐฌ๊ฐ์ง๋ก ์ด ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ์ฃผ์ฒด๋ ํจ์์ ๋๋ค.
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(a, b) {
ย ย ย console.log("bar's this: ", this); // obj
ย ย ย console.log("bar's this.value: ", this.value); // 100
ย ย ย console.log("bar's arguments: ", arguments);
ย ย }
ย ย bar.apply(obj, [1, 2]); // ------- apply๋ ๊ฐ์ฒด bind + ํจ์๋ฅผ ํธ์ถํด์ค.
ย ย bar.call(obj, 1, 2); // ------- call์ ๊ฐ์ฒด bind + ํจ์๋ฅผ ํธ์ถํด์ค
ย ย bar.bind(obj)(1, 2); // ------ bind๋ ๊ฐ์ฒด์ bind๋ง ํด์ฃผ๊ณ ํจ์๋ฅผ ํธ์ถํ์ง๋ ์์.
ย },
};
obj.foo();
[tip]
apply๋ โaโ ๊ธ์๋ก ์์ํ๋๊น 'aโrray์ ์ฐ๊ด ์ง์ด์ ๋ฐฐ์ด์ด argument(์ ๋ฌ์ธ์)๋ก ์จ๋ค๊ณ ์๊ฐํ๋ฉด apply์ call ๊ตฌ๋ถ์ด ์ฝ๋ค.
๋ช ์์ ๋ฐ์ธ๋ฉ์ ์ ์ฌ๋ฐฐ์ด์ด Array.prototye.method๋ฅผ ๋น๋ ค์ ์ฌ์ฉํ ์ ์๋๋ก ์ ์ฉํ๊ฒ ์ฐ์ผ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด HTMLCollection์ ๋ฐํํ๋ getElementsby* ๋ฉ์๋๋ฅผ ์ฌ์ฉํด๋ณด๊ฒ ์ต๋๋ค.

HTMLCollection์ ์ ์ฌ๋ฐฐ์ด์ ํํ๋ฅผ ๋๋ฉฐ nodeList์๋ ๋ค๋ฅด๊ฒ forEach ๋ฉ์๋๊ฐ ํ๋กํ ํ์
์ ์๋ ์ ์ฌ๋ฐฐ์ด์
๋๋ค. ์ด ์ ์ฌ๋ฐฐ์ด์ Array์ ํ๋กํ ํ์
๋ฉ์๋์ธ forEach๋ฅผ ์ฌ์ฉํ๋ ค๊ณ ์๋ํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์๋ฌ๋ฅผ ๋
๋๋ค.
const $collection = document.getElementsByTagName('div');
// HTMLCollection(1044)ย [div#monaco-parts-splash ..., ...]
$collection.forEach(function(col){console.log(col);})
// VM1178:1 Uncaught TypeError: $collection.forEach is not a function at <anonymous>:1:13
์ด ๋ forEach ๋ฉ์๋๋ฅผ ๋น๋ ค์ ์ธ ์ ์๋๋ก Function.prototype ๋ฉ์๋์ธ call ๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ forEach๋ฅผ ๊ฐ์ ๋ก ๋น๋ ค์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
const $collection = document.getElementsByTagName("div");
Array.prototype.forEach.call($collection, function (col: HTMLDivElement) {
ย console.log(col);
});
// ์ฐธ๊ณ ๋ก querySelectorAll์ Live collection์ด ์๋๊ธฐ ๋๋ฌธ์ ์ ์ฌ ๋ฐฐ์ด์ด๋๋ผ๋ ์์ ํ๊ธฐ ๋๋ฌธ์ prototype์ forEach ๋ฉ์๋๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค.
const $List = document.querySelectorAll("div");
$List.forEach(li => console.log(li));

(์ด๋ฐ ์์ผ๋ก forEach ๋น๋ ค์ ์ญ forEach ๋๋ฆด ์ ์์ต๋๋ค.)
๊ทผ๋ฐ ์ต์ ์๋ฐ์คํฌ๋ฆฝํธ์์๋ Array.from ์ผ๋ก ๋ ๊ฐ๋จํ๊ฒ ํ ์ ์์ต๋๋ค.
Array.from($collection).forEach(col => console.log(col));
ย ย ์ ์ฌ ๋ฐฐ์ด ํ๋๋ฅผ ๋ ์์๋ก ๋ค์ด๋ณด๊ฒ ์ต๋๋ค. ์์ฃผ ๋ณด๋(ES6์์๋ ๋ ์ด์ ์ ๋ณด์ด์ง๋ง) ์ ์ฌ๋ฐฐ์ด์ด ํ๋ ๋ ์์ต๋๋ค. function์ arguments์
๋๋ค. ๋ค์๊ณผ ๊ฐ์ด apply๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
function convertArgsToArray() {
ย console.log(arguments); // [Arguments] { '0': 1, '1': 2, '2': 3 }
ย // arguments ๊ฐ์ฒด๋ฅผ ๋ฐฐ์ด๋ก ๋ณํ
ย // slice: ๋ฐฐ์ด์ ํน์ ๋ถ๋ถ์ ๋ํ ๋ณต์ฌ๋ณธ์ ์์ฑํ๋ค.
ย var arr = Array.prototype.slice.apply(arguments); // arguments.slice
ย // var arr = [].slice.apply(arguments);
ย console.log(arr); // [ 1, 2, 3 ]
ย return arr;
}
convertArgsToArray(1, 2, 3);
ย ย ๋ํ ์ฝ๋ฐฑํจ์์๋ ๋ช ์์ ๋ฐ์ธ๋๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ์ฝ๋ฐฑํจ์๊ฐ ์์์ this ๋ฌธ๋งฅ์ ์๋ ์ํฉ์์ ๊ฐ์ ๋ก ๋ช ์์ ๋ฐ์ธ๋ฉ์ ํตํด this๊ฐ ๊ฐ์ ๊ฐ์ฒด๋ฅผ ๋ฐ๋ผ๋ณด๋๋ก ํ ์ ์์ต๋๋ค.
function Person1(name: string) {
ย this.name = name;
}
Person1.prototype.doSomething = function (callback: VoidFunction) {
ย if (typeof callback === "function") {
ย ย // callback.call(this);
ย ย // this๊ฐ ๋ฐ์ธ๋ฉ๋ ์๋ก์ด ํจ์๋ฅผ ํธ์ถ
ย ย callback.call(this);
ย }
};
function foo1() {
ย console.log("#", this.name);
}
const p = new Person1("Mike");
p.doSomething(foo1); // # Mike
์์์ ๋ฐ์ธ๋ฉ(feat. ๋ฉ์๋ ํธ์ถ)
ํจ์๊ฐ ๊ฐ์ฒด์ ํ๋กํผํฐ ๊ฐ์ด๋ฉด ๋ฉ์๋๋ก์ ํธ์ถ๋ฉ๋๋ค. ์ด ๋ ๋ฉ์๋ ๋ด๋ถ์ 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(_a, _b) {
ย ย ย console.log("bar's this: ", this); // obj
ย ย ย console.log("bar's this.value: ", this.value); // 100
ย ย ย console.log("bar's arguments: ", arguments); // [Arguments] { '0': 1, '1': 2 }
ย ย }
ย ย bar.apply(obj, [1, 2]);
ย ย bar.call(obj, 1, 2);
ย ย bar.bind(obj)(1, 2);
ย },
};
obj.foo();
ํ๋กํ ํ์ ๊ฐ์ฒด๋ ๋ฉ์๋๋ฅผ ๊ฐ์ง ์ ์์ต๋๋ค. ํ๋กํ ํ์ ๊ฐ์ฒด ๋ฉ์๋ ๋ด๋ถ์์ ์ฌ์ฉ๋ this๋ ์ผ๋ฐ ๋ฉ์๋ ๋ฐฉ์๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ํด๋น ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ๋ฉ๋๋ค.
function Person(name) {
ย this.name = name;
}
Person.prototype.getName = function () {
ย return this.name;
};
var me = new Person("Lee");
console.log(me.getName()); // Lee
me.age = 30;
Person.prototype.name = "Kim";
console.log(me.name); // Lee
console.log(me.getName()); // Lee
console.log(me.age); // 30
console.log(Person.prototype.name); // Kim
console.log(Person.prototype.getName()); // Kim
console.log(me.prototype); // undefined
console.log(me.prototype.name); // ! Cannot read properties of undefined (reading 'name')
new ๋ฐ์ธ๋ฉ(feat. ์์ฑ์ ํจ์ ํธ์ถ)
ย ย ์๋ฐ์คํฌ๋ฆฝํธ์ ์์ฑ์ ํจ์๋ ๋ง ๊ทธ๋๋ก ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ์ญํ ์ ํฉ๋๋ค. ํ์ง๋ง Java์ ๊ฐ์ ๊ฐ์ฒด์งํฅ ์ธ์ด์ ์์ฑ์ ํจ์์๋ ๋ค๋ฅด๊ฒ ๊ทธ ํ์์ด ์ ํด์ ธ ์๋ ๊ฒ์ด ์๋๋ผ ๊ธฐ์กด ํจ์์ new ์ฐ์ฐ์๋ฅผ ๋ถ์ฌ์ ํธ์ถํ๋ฉด ํด๋น ํจ์๋ ์์ฑ์ ํจ์๋ก ๋์ํฉ๋๋ค.
์ด๋ ๋ฐ๋๋ก ์๊ฐํ๋ฉด ์์ฑ์ ํจ์๊ฐ ์๋ ์ผ๋ฐ ํจ์์ 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
new ์ฐ์ฐ์์ ํจ๊ป ์์ฑ์ ํจ์๋ฅผ ํธ์ถํ๋ฉด this ๋ฐ์ธ๋ฉ์ด ๋ฉ์๋๋ ํจ์ ํธ์ถ ๋์๋ ๋ค๋ฅด๊ฒ ๋์ํฉ๋๋ค.
์์ฑ์ ํจ์ ๋์ ๋ฐฉ์
ย ย new ์ฐ์ฐ์์ ํจ๊ป ์์ฑ์ ํจ์๋ฅผ ํธ์ถํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์์์ผ๋ก ๋์ํฉ๋๋ค.
1. ๋น ๊ฐ์ฒด ์์ฑ ๋ฐ this ๋ฐ์ธ๋ฉ
์์ฑ์ ํจ์์ ์ฝ๋๊ฐ ์คํ๋๊ธฐ ์ ๋น ๊ฐ์ฒด๊ฐ ์์ฑ๋๋ค. ์ด ๋น ๊ฐ์ฒด๊ฐ ์์ฑ์ ํจ์๊ฐ ์๋ก ์์ฑํ๋ ๊ฐ์ฒด์ด๋ค. ์ดํย ์์ฑ์ ํจ์ ๋ด์์ ์ฌ์ฉ๋๋ this๋ ์ด ๋น ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํจ๋ค.ย ๊ทธ๋ฆฌ๊ณ ์์ฑ๋ ๋น ๊ฐ์ฒด๋ ์์ฑ์ ํจ์์ prototype ํ๋กํผํฐ๊ฐ ๊ฐ๋ฆฌํค๋ ๊ฐ์ฒด๋ฅผ ์์ ์ ํ๋กํ ํ์ ๊ฐ์ฒด๋ก ์ค์ ํ๋ค.
2. this๋ฅผ ํตํ ํ๋กํผํฐ ์์ฑ
์์ฑ๋ ๋น ๊ฐ์ฒด์ this๋ฅผ ์ฌ์ฉํ์ฌ ๋์ ์ผ๋ก ํ๋กํผํฐ๋ ๋ฉ์๋๋ฅผ ์์ฑํ ์ ์๋ค. this๋ ์๋ก ์์ฑ๋ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๋ฏ๋ก this๋ฅผ ํตํด ์์ฑํ ํ๋กํผํฐ์ ๋ฉ์๋๋ ์๋ก ์์ฑ๋ ๊ฐ์ฒด์ ์ถ๊ฐ๋๋ค.
3. ์์ฑ๋ ๊ฐ์ฒด ๋ฐํ
- ๋ฐํ๋ฌธ์ด ์๋ ๊ฒฝ์ฐ, this์ ๋ฐ์ธ๋ฉ๋ ์๋ก ์์ฑํ ๊ฐ์ฒด๊ฐ ๋ฐํ๋๋ค. ๋ช ์์ ์ผ๋ก this๋ฅผ ๋ฐํํ์ฌ๋ ๊ฒฐ๊ณผ๋ ๊ฐ๋ค.
function Peep(name) {
ย ย this.name = name;
ย ย return this; // ------- ๋ช
์์ ์ผ๋ก this๊ฐ ๊ฐ๋ฆฌํค๋ ๊ฐ์ฒด ๋ฐํ
}
var me = new Peep('Lee');
console.log(me.name);
์ฐธ๊ณ ๋ก ts์์๋ ๋ช
์์ ์ผ๋ก this ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ฉด ์๋ฌ๋ฅผ ๋
๋๋ค.

- ๋ฐํ๋ฌธ์ด this๊ฐ ์๋ ๋ค๋ฅธ ๊ฐ์ฒด๋ฅผ ๋ช ์์ ์ผ๋ก ๋ฐํํ๋ ๊ฒฝ์ฐ, this๊ฐ ์๋ ํด๋น ๊ฐ์ฒด๊ฐ ๋ฐํ๋๋ค. ์ด๋ this๋ฅผ ๋ฐํํ์ง ์์ ํจ์๋ ์์ฑ์ ํจ์๋ก์์ ์ญํ ์ ์ํํ์ง ๋ชปํ๋ค. ๋ฐ๋ผ์ ์์ฑ์ ํจ์๋ ๋ฐํ๋ฌธ์ ๋ช ์์ ์ผ๋ก ์ฌ์ฉํ์ง ์๋๋ค. (this๋ฅผ ๋ฆฌํดํ์ง ์์ผ๋ฉด ์๋ฌด๋ฆฌ ์์ฑ์ ํจ์๋๋ผ๋ ์์ฑ์ ํจ์๋ฅผ ์ฌ์ฉํ๋ ์๋ฏธ๊ฐ ์๋ค๋ ๋ป)
function Person(name) {
ย // ์์ฑ์ ํจ์ ์ฝ๋ ์คํ ์ -------- 1: ๋น ๊ฐ์ฒด ์์ฑ
ย this.name = name; ย // --------- 2: this๋ฅผ ํตํ ํ๋กํผํฐ ์์ฑ
ย // ์์ฑ๋ ๊ฐ์ฒด ๋ฐํ -------------- 3: ๋ฐํ๋ฌธ์ด ์๋ ๊ฒฝ์ฐ this์ ๋ฐ์ธ๋ฉ๋ ์๋ก ์์ฑํ ๊ฐ์ฒด๊ฐ ๋ฐํ
}
var me = new Person('Lee');
console.log(me.name);
๊ฐ์ฒด ๋ฆฌํฐ๋ด ๋ฐฉ์๊ณผ ์์ฑ์ ํจ์ ๋ฐฉ์์ ์ฐจ์ด โญ
// ๊ฐ์ฒด ๋ฆฌํฐ๋ด ๋ฐฉ์
var foo = {
ย name: 'foo',
ย gender: 'male'
}
console.dir(foo);
// ์์ฑ์ ํจ์ ๋ฐฉ์
function Person(name, gender) {
ย this.name = name;
ย this.gender = gender;
}
var me ย = new Person('Lee', 'male');
console.dir(me);
var you = new Person('Kim', 'female');
console.dir(you);
๊ฐ์ฒด ๋ฆฌํฐ๋ด ๋ฐฉ์๊ณผ ์์ฑ์ ํจ์ ๋ฐฉ์์ ์ฐจ์ด๋ย ํ๋กํ ํ์ ๊ฐ์ฒด(Prototype)์ ์์ต๋๋ค.
-
๊ฐ์ฒด ๋ฆฌํฐ๋ด ๋ฐฉ์์ ๊ฒฝ์ฐ, ์์ฑ๋ ๊ฐ์ฒด์ ํ๋กํ ํ์ ๊ฐ์ฒด๋ Object.prototype์ ๋๋ค.
-
์์ฑ์ ํจ์ ๋ฐฉ์์ ๊ฒฝ์ฐ, ์์ฑ๋ ๊ฐ์ฒด์ ํ๋กํ ํ์ ๊ฐ์ฒด๋ Person.prototype์ ๋๋ค.
์์ฑ์ ํจ์์ new ์ฐ์ฐ์๋ฅผ ๋ถ์ด์ง ์๊ณ ํธ์ถํ ๊ฒฝ์ฐ
ย ย ์ผ๋ฐํจ์์ ์์ฑ์ ํจ์์ ํน๋ณํ ํ์์ ์ฐจ์ด๋ ์์ผ๋ฉฐ ํจ์์ new ์ฐ์ฐ์๋ฅผ ๋ถ์ฌ์ ํธ์ถํ๋ฉด ํด๋น ํจ์๋ ์์ฑ์ ํจ์๋ก ๋์ํฉ๋๋ค.
๊ทธ๋ฌ๋ ๊ฐ์ฒด ์์ฑ ๋ชฉ์ ์ผ๋ก ์์ฑํ ์์ฑ์ ํจ์๋ฅผ new ์์ด ํธ์ถํ๊ฑฐ๋ ์ผ๋ฐํจ์์ new๋ฅผ ๋ถ์ฌ ํธ์ถํ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ์ผ๋ฐํจ์์ ์์ฑ์ ํจ์์ ํธ์ถ ์ this ๋ฐ์ธ๋ฉ ๋ฐฉ์์ด ๋ค๋ฅด๊ธฐ ๋๋ฌธ์
๋๋ค.
์ผ๋ฐ ํจ์๋ฅผ ํธ์ถํ๋ฉด this๋ ์ ์ญ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ๋์ง๋ง, new ์ฐ์ฐ์์ ํจ๊ป ์์ฑ์ ํจ์๋ฅผ ํธ์ถํ๋ฉด this๋ ์์ฑ์ ํจ์๊ฐ ์๋ฌต์ ์ผ๋ก ์์ฑํ ๋น ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ๋ฉ๋๋ค.
function Person(name) {
ย // new์์ด ํธ์ถํ๋ ๊ฒฝ์ฐ, ์ ์ญ๊ฐ์ฒด์ name ํ๋กํผํฐ๋ฅผ ์ถ๊ฐ
ย this.name = name;
};
// ์ผ๋ฐ ํจ์๋ก์ ํธ์ถ๋์๊ธฐ ๋๋ฌธ์ ๊ฐ์ฒด๋ฅผ ์๋ฌต์ ์ผ๋ก ์์ฑํ์ฌ ๋ฐํํ์ง ์๋๋ค.
// ์ผ๋ฐ ํจ์์ this๋ ์ ์ญ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
var me = Person('Lee');
console.log(me); // undefined
console.log(window.name); // Lee
Scope-Safe Constructor(feat. arguments.callee)
ย ย ์ผ๋ฐํจ์์ ์์ฑ์ ํจ์์ ํน๋ณํ ํ์์ ์ฐจ์ด๋ ์๊ธฐ ๋๋ฌธ์ ์ผ๋ฐ์ ์ผ๋ก ์์ฑ์ ํจ์๋ช ์ ์ฒซ๋ฌธ์๋ฅผ ๋๋ฌธ์๋ก ๊ธฐ์ ํ์ฌ ํผ๋์ ๋ฐฉ์งํ๋ ค๋ ๋ ธ๋ ฅ์ ํ๋ค. ๊ทธ๋ฌ๋ ์ด๋ฌํ ๊ท์น์ ์ฌ์ฉํ๋ค ํ๋๋ผ๋ ์ค์๋ ๋ฐ์ํ ์ ์๋ค.
์ด๋ฌํ ์ํ์ฑ์ ํํผํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ ํจํด(Scope-Safe Constructor)์ ๋ค์๊ณผ ๊ฐ๋ค. ์ด ํจํด์ ๋๋ถ๋ถ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ๊ด๋ฒ์ํ๊ฒ ์ฌ์ฉ๋๋ค.
์ฐธ๊ณ ๋ก ๋๋ถ๋ถ์ ๋นํธ์ธ ์์ฑ์(Object, Regex, Array ๋ฑ)๋ new ์ฐ์ฐ์์ ํจ๊ป ํธ์ถ๋์๋์ง๋ฅผ ํ์ธํ ํ ์ ์ ํ ๊ฐ์ ๋ฐํํ๋ค.
๋ค์ ๋งํ์ง๋ง new ์ฐ์ฐ์์ ํจ๊ป ์์ฑ์ ํจ์๋ฅผ ํธ์ถํ๋ ๊ฒฝ์ฐ, ์์ฑ์ ํจ์ ๋ด๋ถ์ this๋ ์์ฑ์ ํจ์์ ์ํด ์์ฑ๋ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํจ๋ค. ๋ฐ๋ผ์ ์๋ A ํจ์๊ฐ new ์ฐ์ฐ์์ ํจ๊ป ์์ฑ์ ํจ์๋ก์จ ํธ์ถ๋๋ฉด A ํจ์ ๋ด๋ถ์ this๋ A ์์ฑ์ ํจ์์ ์ํด ์์ฑ๋ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
// Scope-Safe Constructor Pattern
function A(arg) {
ย // ์์ฑ์ ํจ์๊ฐ new ์ฐ์ฐ์์ ํจ๊ป ํธ์ถ๋๋ฉด ํจ์์ ์ ๋์์ ๋น๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ this์ ๋ฐ์ธ๋ฉํ๋ค.
ย /*
ย this๊ฐ ํธ์ถ๋ ํจ์(arguments.callee, ๋ณธ ์์ ์ ๊ฒฝ์ฐ A)์ ์ธ์คํด์ค๊ฐ ์๋๋ฉด new ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ์ง ์์ ๊ฒ์ด๋ฏ๋ก ์ด ๊ฒฝ์ฐ new์ ํจ๊ป ์์ฑ์ ํจ์๋ฅผ ํธ์ถํ์ฌ ์ธ์คํด์ค๋ฅผ ๋ฐํํ๋ค.
ย arguments.callee๋ ํธ์ถ๋ ํจ์์ ์ด๋ฆ์ ๋ํ๋ธ๋ค. ์ด ์์ ์ ๊ฒฝ์ฐ A๋ก ํ๊ธฐํ์ฌ๋ ๋ฌธ์ ์์ด ๋์ํ์ง๋ง ํน์ ํจ์์ ์ด๋ฆ๊ณผ ์์กด์ฑ์ ์์ ๊ธฐ ์ํด์ 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(10);
console.log(a.value);
console.log(b.value);
arguments.callee
ย ย callee๋ arguments ๊ฐ์ฒด์ ํ๋กํผํฐ๋ก์ ํจ์ ๋ฐ๋ ๋ด์์ ํ์ฌ ์คํ ์ค์ธ ํจ์๋ฅผ ์ฐธ์กฐํ ๋ ์ฌ์ฉํ๋ค. ๋ค์ ๋งํด, ํจ์ ๋ฐ๋ ๋ด์์ ํ์ฌ ์คํ ์ค์ธ ํจ์์ ์ด๋ฆ์ ๋ฐํํ๋ค.
๐ ์ถ๊ฐ ๋ด์ฉ :
- this์ ํ์ดํํจ์(๐ tistory ๋์ฒด ๋งํฌ)
- prototype์ผ๋ก ์ ๊ทผํด์ ํ ๋นํ ๋ณ์์ prototype ๋ฉ์๋ this๋ก ๋ฐ๊พผ ๋ณ์ ๊ฒฐ๊ณผ๊ฐ ํท๊ฐ๋ฆด ๋
์ด ๊ธ์ ์ต์๋์ธ(Obsidian)์์ ์์ฑ๋์์ต๋๋ค. ํฐ์คํ ๋ฆฌ์์ ์๋๊ฒฝ๋ก ๋งํฌ๋ ์๋ํ์ง ์์ต๋๋ค. ํฐ ์ด๋ฏธ์ง ํ์ผ์ ์ ๋ก๋๋์ง ์์ ์ ์์ต๋๋ค.