October 16, 2021
const circle = {}; // using object literal syntax{})๋ฅผ ๊ฐ์ฒด ๋ฆฌํฐ๋ด ๊ตฌ๋ฌธ์ด๋ผ๊ณ ํ๋ค.const circle = {
radius: 1,
location: {
x: 1,
y: 1
},
draw: function() {
console.log('draw');
}
};circle ๊ฐ์ฒด๋ Properties๋ก radius์ location๊ฐ ์๊ณ Methods๋ก draw๊ฐ ์๋ค.circle.draw(); // ์ถ๋ ฅ ๊ฒฐ๊ณผ : draw.)์ผ๋ก ๊ฐ์ฒด์ Properties ๋ฐ Methods์ ์ ๊ทผํ ์ ์๋ค.Bad Example
const circle1 = {
radius: 1,
location: {
x: 1,
y: 1
},
draw: function() {
console.log('draw');
}
};
const circle2 = {
radius: 2,
location: {
x: 2,
y: 2
},
draw: function() {
console.log('draw');
}
};Good Example - Using Factory
// Factory Function
function createCircle(radius, x, y) {
return {
radius,
location: {
x,
y
},
draw: function() {
console.log('draw');
}
};
}
const circle1 = createCircle(1, 1, 1);
const circle2 = createCircle(2, 2, 2);createCircle์ด๋ผ๋ ํจ์๋ฅผ ์์ฑํ๋ค. ์ด ํจ์๋ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๊ณ ๊ฐ์ฒด ๋ด์ ์์ฑ์ ํจ์์ ๋งค๊ฐ๋ณ์๋ก ๋ฐ์์ค๋๋ก ์ฒ๋ฆฌํ๋ค.// Constructor Function
function Circle(radius, x, y) {
this.radius = radius;
this.location = {
x,
y
}
this.draw = function() {
console.log('draw');
}
}
const myCircle = new Circle(1, 1, 1);
console.log(myCircle.radius); // 1{})๋ฅผ ์์ฑํ๋๋ก ํ๊ณ ํจ์ ๋ด this๋ ์ด ๋น ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ๋๋ค.this๊ฐ ์ด ๋น ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๊ณ ์ด ๋น ๊ฐ์ฒด์ this.radius ์ ๊ฐ์ ๋ฐฉ์์ผ๋ก Properties์ Methods๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ด๋ค.return this๋ฅผ ํ๊ฒ ๋๋ค.myCircle์ ํ ๋นํ๊ณ ์๊ธฐ ๋๋ฌธ์ myCircle.radius ์ ์ถ๋ ฅํ๋ฉด ์ ์์ ์ผ๋ก 1์ด ์ถ๋ ฅ๋๋ค.const badCircle = Circle(2, 2, 2);์ ๊ฐ์ด ์์ฑํ๋ค๋ฉด ํจ์ ๋ด this๋ badCircle๊ฐ ์๋ Window(๋ธ๋ผ์ฐ์ ๊ธฐ์ค)๊ฐ ๋๋ค.constructor ์์ฑ
console.log(myCircle.constructor); // f Circle(...) {...}
console.log(Circle.constructor); // f Object() {...}myCircle.constructor๋ Circle ํจ์๋ฅผ ๊ฐ๋ฆฌํจ๋ค.Circle.constructor๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ๋ด์ฅ๋ ํจ์์ธ Object ํจ์์ด๋ค.function Circle(radius, x, y) {
this.radius = radius;
this.location = {
x,
y
}
this.draw = function() {
console.log('draw');
}
}
const myCircle = new Circle(1, 1, 1);Circle ํจ์๋ ์ฌ์ค ํ๋์ Object๋ค.Circle. ์ ์
๋ ฅํ๋ฉด ์ ๊ทผํ ์ ์๋ ๋ฉค๋ฒ(methods, properties)๋ค์ด ์๋ ์ถ์ฒ ๋ชฉ๋ก์ผ๋ก ๋ฌ๋ค.
(ex. apply, arguments, bind, call, caller, length, name, prototype, toString, โฆ)
Circle ํจ์๋ ํ๋์ ๊ฐ์ฒด์ด๋ฏ๋ก Constructor ์์ฑ์ ๊ฐ์ง๊ณ , ์ด Constructor๋ ์ด Circle์ ์์ฑํ ๋ ์ฌ์ฉ๋ ํจ์๋ฅผ ๊ฐ๋ฆฌํจ๋ค.Circle.constructor ์ ์ถ๋ ฅํด๋ณด๋ฉด ฦ Function() { [native code] } (์๋ฐ์คํฌ๋ฆฝํธ์ ๋ด์ฅ๋ Constructor์ธ function)๊ฐ ์ถ๋ ฅ๋๋ค.function Circle() {...} ์ ๊ฐ์ด ํจ์๋ฅผ ์ ์ธํ ๋, ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ function constructor์ ์ด์ฉํด์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ฒ ๋๋ค.JavaScript์๋ ๋ ๊ฐ์ง ํ์ ์ข ๋ฅ๊ฐ ์กด์ฌํ๋ค.
Value Types (Primitives)
Reference Types
Primitives
let x = 10;
let y = x;
x = 20;
console.log(x); // 20
console.log(y); // 10x์ y๋ ์์ ํ ๋
๋ฆฝ๋ ๋ ๊ฐ์ ๋ณ์์ด๋ค.x์ 10์ ํ ๋นํ๊ณ ๊ทธ ์ดํ์ y์ x๋ฅผ ํ ๋นํ ํ x์ 20์ผ๋ก ์ฌํ ๋นํ๋ฉด x๋ 20์ผ๋ก ๋ณ๊ฒฝ๋์ง๋ง y๋ x์ ๋ณ๊ฒฝ๊ณผ๋ ์๊ด์์ด ์ฌ์ ํ 10์ด๋ค. Objects
let x = { value: 10 };
let y = x;
x.value = 20;
console.log(x.value); // 20
console.log(y.value); // 20x.value์ y.value๋ ๋ชจ๋ 20์ด๋ค.let y = x; ์ ๊ฐ์ด y์ x๋ฅผ ํ ๋นํ๊ฒ ๋๋ฉด ์ฐธ์กฐ ํ ๋น์ด ์ผ์ด๋๋ค. ์ฆ, ๊ฐ์ฒด ์์ฒด๊ฐ ๋ณต์ฌ๋์ด ์๋ก์ด ๋ฉ๋ชจ๋ฆฌ์ ํ ๋น๋๋ ๊ฒ์ด ์๋๋ผ ํด๋น ๊ฐ์ฒด๊ฐ ์ ์ฅ๋์ด ์๋ ๋ฉ๋ชจ๋ฆฌ์ ์ฃผ์๊ฐ์ด ๋ณต์ฌ๋๋ ๊ฒ์ด๋ค. x์ y๋ ๋์ผํ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ๋๊ณ x.value์ ๊ฐ์ ๋ณ๊ฒฝํ๋ฉด y.value์ ๊ฐ๋ ๋ณ๊ฒฝ๋๋ ๊ฒ์ด๋ค.
๊ฒฐ๋ก
Primitives are copied by their value - Example
let number = 10;
function increase(number) {
number++;
}
increase(number);
console.log(number); // 10;increase ํจ์๋ฅผ ํธ์ถํ ๋ ํจ์์์ ๋ฐ์ number๋ผ๋ ๋งค๊ฐ๋ณ์๋ ์ฝ๋ 1ํ์ number์๋ ์์ ํ ๋ณ๊ฐ์ ๋ณ์์ด๋ค.number์ ๊ฐ์ ์ฆ๊ฐ์ํค๋๋ผ๋ 1ํ์ number์๋ ์๊ด์ด ์๊ธฐ ๋๋ฌธ์ ์ฝ๋ ๋ง์ง๋ง ํ์์ number๊ฐ์ ์ถ๋ ฅํ๋ฉด 10์ด ์ถ๋ ฅ๋๋ค. Objects are copied by their reference - Example
let obj = { value: 10 };
function increase(obj) {
obj.value++;
}
increase(obj);
console.log(obj.value); // 11;increase ํจ์๋ฅผ ํธ์ถํ ๋ ํจ์์์ ๋ฐ์ obj๋ผ๋ ๋งค๊ฐ๋ณ์๋ ์ฝ๋ 1ํ์ obj์๋ ๋ณ๊ฐ์ ๋ณ์์ด์ง๋ง ๊ฐ์ ๊ฐ์ฒด { value: 10 }์ ๊ฐ๋ฆฌํจ๋ค. (๊ฐ์ฒด๋ ์ฐธ์กฐ ๋ณต์ฌ๊ฐ ๋๊ธฐ ๋๋ฌธ.)obj.value์ ๊ฐ์ ์ฆ๊ฐ์ํค๋ฉด 1ํ์ obj๋ ๊ฐ์ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๊ณ ์๊ธฐ ๋๋ฌธ์ ์ฝ๋ ๋ง์ง๋ง ํ์์ obj.value๋ฅผ ์ถ๋ ฅํ๋ฉด 11์ด ์ถ๋ ฅ๋๋ค.function Circle(radius) {
this.radius = radius;
this.draw = function() {
console.log('draw');
}
}
const circle = new Circle(10); // circle object ์์ฑ
circle.location = { x: 1 }; // location ์์ฑ ์ถ๊ฐ
console.log(circle); // { radius: 10, location: { x: 1 }, draw: f }
circle['name'] = 'c1';
console.log(circle); // { radius: 10, location: { x: 1 }, name: 'c1', draw: f }
delete circle['location'];
delete circle.name;.์ด๋ [] ์ผ๋ก ์ ๊ทผ/์ถ๊ฐํ ์ ์๋ค..)์ Brackets Notation([])๋ณด๋ค ํ๊ธฐ๋ฒ์ด ์ฌํํ๋ค.[])์ ๋์ ์ธ ์์ฑ๋ช
์ผ๋ก ์ ๊ทผํ ๋ ์ ์ฉํ๋ค. ex) circle[propertyName]๋ํ Bracket([])์ ์ ํจํ ์๋ณ์๊ฐ ์๋ ์์ฑ ์ด๋ฆ์ ์ฌ์ฉํ ๋ ์ ์ฉํ๋ค.
circle.center-location๊ณผ ๊ฐ์ ์ ๊ทผ์ ๋ถ๊ฐ๋ฅํ๋ค.circle['center-location']๊ณผ ๊ฐ์ ์ ๊ทผ์ ๊ฐ๋ฅํ๋ค.delete Operator ๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค. for in loop
function Circle(radius) {
this.radius = radius;
this.draw = function() {
console.log('draw');
}
}
const circle = new Circle(10);
for (let key in circle) {
console.log('key is ' + key);
console.log('value is ' + circle[key]);
}circle[key]์ ๊ฐ์ด ์ ๊ทผํ๋ฉด ๋๋ค.Object.keys()
const keys = Object.keys(circle);
console.log(keys); // ["radius", "draw"]in operator
if ('radius' in circle) {
console.log('Circle has a radius')
}function Circle(radius) {
this.radius = radius;
this.defaultLocation = {
x: 0,
y: 0,
};
this.computeOptimumLocation = function() {
// ...
}
this.draw = function() {
this.computeOptimumLocation();
console.log('draw');
}
}
const circle = new Circle(10);
circle.defalutLocation = false; // Bad
circle.computeOptimumLocation(); // Badcircle.defaultLocation์ ๋ฌ๊ธ์์ด false๋ฅผ ํ ๋นํ๋ค๊ฑฐ๋,draw ๋ฉ์๋ ์์์๋ง ํธ์ถ ๋๊ธฐ๋ฅผ ๋ฐ๋ผ๋ computeOptimumLocation ๋ฉ์๋๋ฅผ ์ง์ ์ ์ผ๋ก ํธ์ถํ๋ฉด ๊ฐ์ฒด๋ฅผ ๋์ ์ํ๋ก ๋ง๋ค ์ ์๋ค.Circle ํจ์์์ radius์ draw๋ง ์ธ๋ถ์์ ์ ๊ทผ ๊ฐ๋ฅํ๋๋ก ํ๊ณ defaultLocation๊ณผ computeOptimumLocation์ ์ธ๋ถ์์ ์ ๊ทผ ๋ถ๊ฐ๋ฅํ๋๋ก ํด๋ณด์. function Circle(radius) {
this.radius = radius;
let defaultLocation = {
x: 0,
y: 0,
};
let computeOptimumLocation = function() {
// ...
}
this.draw = function() {
computeOptimumLocation();
console.log('draw');
}
}
const circle = new Circle(10);this.defaultLocation ๋์ let defaultLocation๊ณผ ๊ฐ์ด ๋ก์ปฌ ๋ณ์๋ก ์ ์ํ๋ฉด ํจ์ ์ธ๋ถ๋ก๋ถํฐ ์จ๊ธธ ์ ์๋ค.defaultLocation๊ณผ computeOptimumLocation์ ์ธ๋ถ์์ ์ง์ ์ ๊ทผ์ด ๋ถ๊ฐ๋ฅํ๋๋ก ๋ง๋ค๊ณ ์ถ๊ธฐ ๋๋ฌธ์ ๋ก์ปฌ ๋ณ์๋ก ๋ณ๊ฒฝํ๊ณ draw ๋ฉ์๋ ๋ด์์ ํธ์ถํ๊ณ ์์๋ this.computeOptimumLocation() ๋์ computeOptimumLocation() ์ผ๋ก ๋ณ๊ฒฝํ๋ค.draw ๋ฉ์๋ ๋ด์์ computeOptimumLocation์ ํธ์ถํ๋ฉด Circle ์ธ๋ถ์์ draw ๋ฉ์๋๋ฅผ ํธ์ถํ ๋ computeOptimumLocation์ด ์ ์์ ์ผ๋ก ์คํ๋๋๋ฐ,์์์๋ ํจ์ ์ธ๋ถ์์ ์ ๊ทผํ์ง ๋ชปํ๋๋ก ํ๋ ๋ฐฉ๋ฒ์ผ๋ก ๋ก์ปฌ ๋ณ์๋ฅผ ๋์๋๋ฐ
์ด๋ป๊ฒ ํ๋ฉด ํจ์ ์ธ๋ถ์์ ์์ ์ ๋ชปํ๋๋ก ํ๊ณ ์ฝ๊ธฐ๋ง ๊ฐ๋ฅํ๋๋ก ํ ์ ์์๊น?
function Circle(radius) {
this.radius = radius;
let defaultLocation = {
x: 0,
y: 0,
};
this.getDefaultLocation = function() {
return defaultLocation;
}
this.draw = function() {
console.log('draw');
}
}
const circle = new Circle(10);
console.log(circle.getDefaultLocation()); // { x: 0, y: 0 }defaultLocation์ด๋ผ๋ ๋ณ์๋ Circle ํจ์ ์ธ๋ถ์์ ์ง์ ์ ์ผ๋ก ์ ๊ทผ์ ๋ถ๊ฐ๋ฅํ์ง๋งgetDefaultLocation์ด๋ผ๋ ํจ์๋ฅผ ํตํด์ (ํด๋ก์ ๊ฐ๋
์ ์ด์ฉํด) defaultLocation ๋ณ์๋ฅผ ์กฐํํ ์ ์๋ค. (์์ ์ ๋ถ๊ฐ๋ฅ)function Circle(radius) {
this.radius = radius;
let defaultLocation = {
x: 0,
y: 0,
};
this.draw = function() {
console.log('draw');
}
Object.defineProperty(this, 'defaultLocation', {
get: function() {
return defaultLocation;
}
});
}
const circle = new Circle(10);
console.log(circle.defaultLocation); // { x: 0, y: 0 }get ์ด๋ผ๋ ์ด๋ฆ์ key๋ฅผ ์ง์ ํด์ฃผ๊ณ value๋ก๋ ํจ์๋ฅผ ๋ฃ์ด์ค๋ค.circle.defaultLocation๊ณผ ๊ฐ์ด ์ ๊ทผํ๋ฉด ์ด get ํจ์๊ฐ ํธ์ถ๋๋ ๊ฒ์ด๋ค. circle ๊ฐ์ฒด๋ฅผ ์ถ๋ ฅ ํด๋ณด๋ฉด ์๋์ ๊ฐ์ด ์๋ก์ด property์ธ defaultLocation์ด ์ถ๊ฐ๋ ๊ฒ์ ๋ณผ ์ ์๋ค. ์ด๊ฒ์ read-only ์์ฑ์ด๋ค. ๋ง์ฝ์ ์ด ์์ฑ์ ๋ณ๊ฒฝํ๊ณ ์ถ๋ค๋ฉด setters๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
function Circle(radius) {
this.radius = radius;
let defaultLocation = {
x: 0,
y: 0,
};
this.draw = function() {
console.log('draw');
}
Object.defineProperty(this, 'defaultLocation', {
get: function() {
return defaultLocation;
},
set: function(value) {
if (!value.x || !value.y) {
throw new Error('Invalid location.');
}
defaultLocation = value;
}
});
}
const circle = new Circle(10);
circle.defaultLocation = { x: 10, y: 20};
console.log(circle.defaultLocation); // { x: 10, y: 20 }