JavaScript Prototype & ES6 Class
Deep dive into JavaScript prototype
1. How to create the Object π©βπ»
κ°μ²΄ μμ± κ³Όμ μ ν΅ν΄ JavaScript Object μ Prototype μ μ΄ν΄νκ³ ES6 μ μΆκ°λ ES6 Class Syntax μ λΉκ΅ν΄λ³΄μ.
1. Object (Constructor Function)
JavaScript μ κ°μ²΄λ μ΅μμμ Object
λΌλ κ°μ²΄λ₯Ό λκ³ , κ·Έ κ°μ²΄λ₯Ό μ°κ²°ν΄ νμ κ΅¬μ‘°λ‘ μ¨λ΄λ €κ°λ€. λ°λΌμ JavaScript λ₯Ό Prototype
Language λΌ λΆλ₯΄λ©°, μ΄λ€κ°μ κ΄κ³λ₯Ό Prototype Chain μ΄λΌ νλ€.
κ·Έλ¦¬κ³ μ’ λ λͺ νν μ΄μΌκΈ°νλ©΄ JavaScript μλ Interfaces λΏ μλλΌ Classes μμ μ‘΄μ¬νμ§ μλλ€. ES6 μ΄μ λ¬Έλ²μμλ μμ±μλ₯Ό λ€μκ³Ό κ°μ΄ λ§λ€ μ μμλ€.
function Person(name, age) {
this.name = name
this.age = age
this.greet = function () {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`)
}
}
νμ§λ§ μ λ°©λ²μ λ©λͺ¨λ¦¬λ₯Ό κ³Όλνκ² μ¬μ©ν μ μλ λ¬Έμ μ μ κ°λλ€. Class λ₯Ό μ¬μ©νκ² λ€λ κ²μ μ¬μ¬μ©μ νκΈ° μν¨μ΄λ€. κ·Έλ°λ° μμ κ°μ΄ μμ±μ ν¨μμ λ©μλκ° ν¬ν¨λλ κ²½μ°, 2κ°μ instance λ₯Ό μμ±νλ©΄ κ°κ° instance κ° λ©μλ μμ κ°κ° μμ±νλ€. μΌλ°μ μΌλ‘ Class κ°μ²΄κ° λ©μλλ₯Ό 곡μ νμ§λ§ Properties μ Closures λ§ μμ μ instance μ μ μ₯νλ κ²κ³Ό λ¬λ¦¬ μ΄ λ°©λ²μ λͺ¨λ κ²μ κ°κ° μμ μ instance μ μ μ₯νλ λ¬Έμ μ μ κ°λ κ²μ΄λ€.
λ°λΌμ μ΄ λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ λ€μκ³Ό κ°μ΄ Constructor λ§ μ μν ν Methods λ₯Ό Prototype Chain μ μ΄μ©ν΄ μΆκ°νλ κ²μΌλ‘ λ³κ²½ν μ μλ€.
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.greet = function () {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`)
}
μ΄λ κ² μμ±νλ©΄ μ¬λ¬ κ°μ instance λ₯Ό μμ±νλλΌλ Prototype μ ν΅ν΄ λ©μλλ₯Ό 곡μ ν μ μλ€.
2. Object (ES6 Class Syntax)
μμμ μμ±ν μμ±μ μ½λλ₯Ό ES6 μμ μΆκ°λ Class Syntax λ‘ λ³κ²½νλ©΄ λ€μκ³Ό κ°λ€.
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
greet() {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`)
}
}
const person = new Person('νκΈΈλ', 25)
person.greet() // Hello, my name is νκΈΈλ and I'm 25 years old.
ES6 μ Class Syntax λ λ΄λΆμ μΌλ‘λ 1. μμ±μ ν¨μλ₯Ό μμ±
νκ³ , 2. Prototype μ λ©μλλ₯Ό λ±λ‘
νλ λΆλ¦¬λ λ‘μ§μ μλν μμΌμ£Όλ
Syntactic Sugar μ κ°κΉμ΄ λ¬Έλ²μ΄λ€.
λ¨, ν μΈμ΄μμ μκ°νλ Class μλ ꡬ쑰μ μΌλ‘, κΈ°λ₯μ μΌλ‘ λ§μ μ°¨μ΄λ₯Ό κ°λλ€. μ΄λ JavaScript μ λ¬Έλ²μ νΉμ±μ΄λ μ΄λ₯Ό λͺ νν μ΄ν΄νκ³ μ¬μ©νλ κ²μ΄ μ€μνλ€.
3. Object Literal
Class λ₯Ό μ¬μ©νλ μ΄μ λ instance μμ±μ μ¬μ¬μ© νκΈ° μν¨μ΄λ€. κ·Έλ°λ° instance μμ±μ μ¬μ¬μ© ν νμκ° μλ νλμ½λ©λ κ°μ²΄λΌλκ°
instance μμ±μ ν λ²λ§ νλ Singleton κ°μ²΄μ κ°μ κ²λ€μ μμ½κ² Object Literal μ μ΄μ©ν΄ μμ±ν μ μλ€.
- νλμ½λ© λ κ°μ²΄
const Person = {
name: 'νκΈΈλ',
age: 25,
greet: function () {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`)
}
}
- Singleton κ°μ²΄
const Person = {
name: '',
age: 0,
init(name: string, age: number) {
this.name = name
this.age = age
},
greet() {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`)
}
}
Person.init('νκΈΈλ', 25)
console.log(Person.greet()) // Hello, my name is νκΈΈλ and I'm 25 years old.
JavaScript μ Class λ Object μ Prototype κ°μ²΄μ μμ±μ ν¨μλ₯Ό λ€λ₯Έ μΈμ΄μ Class λ¬Έλ²κ³Ό μ μ¬νκ² λ§λ€μ΄ μ¬μ©νκΈ° μ½κ² ν΄μ£Όλ Syntactic Sugar μ κ°κΉκΈ° λλ¬Έμ μ΄λ°μμ μμ±μ΄ κ°λ₯νλ€.
Object Literal λ°©μμ
Singleton
κ°μ²΄λ₯Ό μμ±νλ€. λ€λ₯Έ μΈμ΄μμ Singleton Class λ₯Ό ꡬννκΈ° μν΄ μ¬μ©νλprivate initializer
μ Instance λ₯Ό μμ±νλ λ©μλ, Synchronous μ²λ¦¬μ κ°μ κ²λ€ μμ΄ μμ½κ² Singleton μ ꡬνν μ μλ€.
4. Closures (Functional Programming)
λ§μ§λ§μΌλ‘ μμ ν ν¨μνμΌλ‘ Closures λ₯Ό μ¬μ©ν κ°μ²΄ μμ± λ°©λ²μ΄λ€.
function Person(name: string, age: number) {
let _name = name
let _age = age
function getName(): string {
return _name
}
function setName(name: string) {
_name = name
}
function getAge(): number {
return _age
}
function setAge(age: number) {
_age = age
}
function greet() {
console.log(`Hello, my name is ${_name} and I'm ${_age} years old.`)
}
return {
getName, setName, getAge, setAge, greet
}
}
const person = Person('νκΈΈλ', 25)
person.greet() // Hello, my name is νκΈΈλ and I'm 25 years old.
5. Arrow Functions are not equal to Functions
ES6 μμ Arrow Functions κ° μκ°λ μ΄νλ‘ κΈ°μ‘΄μ Functions λ¬Έλ²μ λΉ λ₯΄κ² λ체νκ³ μλ€. Arrow Functions κ° κ°λ μ₯μ μ λ€μκ³Ό κ°λ€.
- Lambda Expression κΈ°λ°μΌλ‘ κ°λ μ±μ΄ λ°μ΄λλ€.
- ν¨μκ° νΈμΆλ λ λμ μΌλ‘ this κ° binding λλ μΌλ° ν¨μμ λ¬λ¦¬ μ μΈν λ μμ Scope μ this λ₯Ό κΈ°μ΅νλ€. μ΄λ₯Ό
Lexical Scope
λΌ νλ€.
λ¬Έμ λ μ 2λ²μ§Έ λμ μΈ this μμ μ μ μΈ this λ₯Ό μ¬μ©ν μ μμ§λ§ μ€νλ € μμ Scope λ₯Ό κ°λ¦¬ν€λ λ¬Έμ λ‘ μΈν΄ λ©μλμ μμ±ν λλ μλͺ»λ λμμ
κ°λ¦¬ν€κ² λλ€λ λ¬Έμ κ° μλ€. λ€λ₯Έ μΈμ΄μμλ κ°μ²΄ λ΄μμ λ©μλκ° this λ₯Ό κ°λ¦¬ν€λ©΄ Method body context λ₯Ό κΈ°μ€μΌλ‘ λ°κΉ₯μͺ½μ ν΄λΉνλ μκΈ° μμ μ΄
μν κ°μ²΄λ₯Ό this λ‘ κ°λ¦¬ν€μ§λ§ JavaScript μ Arrow Functions μμ this λ Method body context κ° μλ Method λ₯Ό κΈ°μ€μΌλ‘ λ°κΉ₯μͺ½μ
this λ‘ κ°λ¦¬ν¨λ€.
const something2 = {
whoAreYou: 'something2',
aTraditionalFunction: function () {
console.log(this.whoAreYou)
},
aArrowFunction: () => console.log(this.whoAreYou)
}
something2.aTraditionalFunction() // something2
something2.aArrowFunction() // undefined
something2 μ this κ° κ°λ¦¬ν€λ λμμ΄ λꡬ길λ undefined κ° μΆλ ₯λ κΉ?
const something2 = {
whoAreYou: 'something2',
aTraditionalFunction: function () {
console.log(this)
},
aArrowFunction: () => console.log(this)
}
something2.aTraditionalFunction() // {whoAreYou: 'something2', aTraditionalFunction: Ζ, aArrowFunction: Ζ}
something2.aArrowFunction() // Window {window: Window, self: Window, document: document, name: '', location: Location, β¦}
Arrow Functions μ this λ something2 κ°μ²΄μ λ°κΉ₯μͺ½μ κ°λ¦¬ν€κ³ μλ€. Window κ°μ²΄μ βwhoAreYouβ κ° μ μλ μ μ‘°μ°¨ μμΌλ―λ‘ undefined κ° μΆλ ₯λλ κ²μ΄λ€.
κ·Έλ¬λ©΄ λ€μμ κ²½μ°λ μ΄λ¨κΉ?
const something1 = {
whoAreYou: 'something1',
something2: {
whoAreYou: 'something2',
aTraditionalFunction: function () {
console.log(this.whoAreYou)
},
aArrowFunction: () => console.log(this.whoAreYou)
}
}
something1.something2.aTraditionalFunction() // something2
something1.something2.aArrowFunction() // undefined
something2 λ₯Ό something1 λ΄λΆμ μ μνλ€. μ¬κΈ°μ this λ something1 μ κ°λ¦¬ν€κ³ , βsomething1β μ΄ μΆλ ₯λ κ²μΌλ‘ μμν μ μμ§λ§ μ¬μ ν undefined κ° μΆλ ₯λλ€.
const something1 = {
whoAreYou: 'something1',
something2: {
whoAreYou: 'something2',
aTraditionalFunction: function () {
console.log(this)
},
aArrowFunction: () => console.log(this)
}
}
something1.something2.aTraditionalFunction() // {whoAreYou: 'something2', aTraditionalFunction: Ζ, aArrowFunction: Ζ}
something1.something2.aArrowFunction() // Window {window: Window, self: Window, document: document, name: '', location: Location, β¦}
μ¬μ ν Window κ°μ²΄λ₯Ό κ°λ¦¬ν¨λ€βΌοΈπ€―π€―
μ μ΄λ° νμμ΄ μΌμ΄λλ κ²μΌκΉ? μ μΈν λ μμ Scope μ this λ₯Ό κΈ°μ΅
νλ€κ³ νλ€. μλ κ°μ²΄κ° μμ±λλ κ³Όμ μ νμ΄μ 보면 λ€μκ³Ό κ°λ€.
const something1 = {
whoAreYou: 'something1',
}
const something2 = {
whoAreYou: 'something2',
aTraditionalFunction: function () {
console.log(this.whoAreYou)
},
aArrowFunction: () => console.log(this.whoAreYou)
}
something1.something2 = something2
μ¦, something2 Instance κ° μμ±λλ μμ μ this λ Window λ₯Ό κ°λ¦¬ν¨λ€. Instance κ° μμ±λ ν something1 μ something2 Property μ ν λΉλκΈ° λλ¬Έμ ν΄λΉ Arrow Functions κ° μ μΈλκ³ μ μλλ μμ μ this λ Window κ°μ²΄κ³ μ΄λ₯Ό κΈ°μ΅νκΈ° λλ¬Έμ΄λ€.
μ¦, λ©μλλ₯Ό μμ±ν λ Arrow Functions λ₯Ό μ¬μ©νλ κ²μ μμ μ΄ μν Object κ°μ²΄λ₯Ό this λ‘ κ°λ¦¬ν€μ§ μκΈ° λλ¬Έμ μΌλ°μ μΈ κ°μ²΄μ λ©μλλ‘μ¨μ κΈ°λ₯μ μνν μ μλ€.
Arrow Functions λ λ¨μ§ Syntax λ§ λ€λ₯Έ κ²μ΄ μλ κΈ°μ‘΄μ ν¨μμλ λ€λ₯Έ κΈ°λ₯μ κ°λ μλ‘μ΄ ν¨μ λΌλ μ μ μμ΄μλ μ λλ€.
2. Prototype Chain π©βπ»
μ΄λ²μλ μμμ μ΄ν΄λ³Έ Prototype μ΄ μ€μ λ‘ μ΄λ»κ² Chaining λλμ§ νμΈν΄λ³Έλ€.
1. Constructor Function
function Person(name, age) {
this.name = name
this.age = age
this.greet = function () {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`)
}
}
console.dir(Person)
- constructor: f Person(name, age)
- Prototype Chain: self -> Base Object
2. ES6 Class Syntax
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
greet() {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`)
}
}
console.dir(Person.prototype)
- constructor: class Person
- Prototype Chain: self -> Base Object
3. Object Literal
const Person = {
name: 'νκΈΈλ',
age: 25,
greet() {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`)
}
}
console.dir(Person.__proto__)
- constructor: none
- Prototype Chain: Base Object
3. Inheritance π©βπ»
1. Constructor Function
1 ) Superclass
function Person(name, age) {
this.name = name
this.age = age
this.greet = function () {
console.log(`Hello, my name is ${this.name}, I'm ${this.age} years old.`)
}
}
2 ) Subclass
function Student(name, age, grade) {
Person.call(this, name, age)
this.grade = grade
this.study = function () {
console.log(`I'm studying in grade ${this.grade}.`)
}
}
const student = new Student("Jane", 20, 2)
student.greet() // Hello, my name is Jane, I'm 20 years old.
student.study() // I'm studying in grade 2.
μμμΌλ‘ μ μλνλ κ²μ λ³Ό μ μλ€.
student Instance -> Student Object -> Person Object -> Base Object
2. ES6 Class Syntax
1 ) Superclass
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
greet() {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`)
}
}
2 ) Subclass
class Student extends Person {
constructor(name, age, grade) {
super(name, age)
this.grade = grade
}
study() {
console.log(`I'm studying in grade ${this.grade}.`)
}
}
const student1 = new Student("Jane", 20, 2)
student1.greet() // "Hello, my name is Jane and I'm 20 years old."
student1.study() // "I'm studying in grade 2."
Parent κ° ES6 Class Syntax λ₯Ό μ¬μ©νλ€λ©΄, Children μμ ES6 Class Syntax λ₯Ό μ¬μ©ν΄μΌνλ€!!
ππ» μ΄ κ²½μ° Children μμ Parent μPerson.call(this, name, age)
λ₯Ό νΈμΆν μ μλ€.λ¨, λ°λμ κ²½μ° Parent κ° Constructor Function μ μ¬μ©νλλΌλ Children μ ES6 Class Syntax λ₯Ό μ¬μ©ν΄ μμνλ κ²μ΄ κ°λ₯νλ€.
4. Two Phase Initialization π©βπ»
1. Constructor Function
1 ) Super μ Constructor νΈμΆ μμ μ΄ μ€μνμ§ μμ κ²½μ°
function Person(name, age) {
this.name = name
this.age = age
this.greet = function () {
console.log(`Hello, my name is ${this.name}, I'm ${this.age} years old.`)
}
}
Parent κ°μ²΄μ κ°μ΄ Constructor λ₯Ό ν΅ν΄ μ΄κΈ°νκ° κ°λ₯νλ€λ©΄, Children κ°μ²΄μ Constructor κ° Super μ Constructor λ₯Ό νΈμΆνλ μμ μ΄ κ°μ μ μ₯ν νλ νΈμΆ ν μ μ₯μ νλ Prototype μ μν΄ μλ¬΄λ° μν₯μ λ―ΈμΉμ§ μλλ€.
function Student(name, age, grade) {
this.name = name
this.age = age
this.grade = grade
Person.call(this, name, age)
this.study = function () {
console.log(`I'm studying in grade ${this.grade}.`)
}
}
const student = new Student("Jane", 20, 2)
console.log(student) // Student {name: 'Jane', age: 20, grade: 2, greet: Ζ, study: Ζ}
function Student(name, age, grade) {
Person.call(this, name, age)
this.name = name
this.age = age
this.grade = grade
this.study = function () {
console.log(`I'm studying in grade ${this.grade}.`)
}
}
const student = new Student("Jane", 20, 2)
console.log(student) // Student {name: 'Jane', age: 20, grade: 2, greet: Ζ, study: Ζ}
2 ) Super μ Constructor νΈμΆ μμ μ΄ μ€μν κ²½μ°
function Person() {
this.name = 'νκΈΈλ'
this.age = 25
this.greet = function () {
console.log(`Hello, my name is ${this.name}, I'm ${this.age} years old.`)
}
}
νμ§λ§ μμ κ°μ΄ Parent κ°μ²΄μ κ°μ΄ Constructor λ₯Ό ν΅ν΄ μ΄κΈ°νκ° κ°λ₯ν κ°μ΄ μλ κ²½μ° Super μ Constructor λ₯Ό νΈμΆνλ μμ μ΄ μ€μν΄μ§λ€.
function Student(name, age, grade) {
this.name = name
this.age = age
this.grade = grade
Person.call(this, name, age)
this.study = function () {
console.log(`I'm studying in grade ${this.grade}.`)
}
}
const student = new Student("Jane", 20, 2)
console.log(student) // Student {name: 'νκΈΈλ', age: 25, grade: 2, greet: Ζ, study: Ζ}
Jane
μ΄ μλνκΈΈλ
μ΄ μμ±λλ κ²μ λ³Ό μ μλ€!!
function Student(name, age, grade) {
Person.call(this, name, age)
this.name = name
this.age = age
this.grade = grade
this.study = function () {
console.log(`I'm studying in grade ${this.grade}.`)
}
}
const student = new Student("Jane", 20, 2)
console.log(student) // Student {name: 'Jane', age: 20, grade: 2, greet: Ζ, study: Ζ}
3 Recommend Way
JavaScript μμ Subclass μ Constructor λ νμ Superclass μ Constructor λ₯Ό μμ±ν ν κ°μ μμ λλ μ μνλλ‘ νλ€!!
function Student(name, age, grade) {
Person.call(this, name, age)
this.name = name
this.age = age
this.grade = grade
this.study = function () {
console.log(`I'm studying in grade ${this.grade}.`)
}
}
const student = new Student("Jane", 20, 2)
console.log(student) // Student {name: 'Jane', age: 20, grade: 2, greet: Ζ, study: Ζ}
2. ES6 Class Syntax
λ¨, ES6 Class Syntax λ₯Ό μ¬μ©νμ κ²½μ°λ μ’ λ μ격νκ² κ·μΉμ΄ μ μ©λλ€.
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
greet() {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`)
}
}
λ°λΌμ λ€μμ μλ¬κ° λ°μνλ€.
class Student extends Person {
constructor(name, age, grade) {
this.name = name // error, 'this' is not allowed before superclass constructor invocation.
this.age = age // error, 'this' is not allowed before superclass constructor invocation.
this.grade = grade // error, 'this' is not allowed before superclass constructor invocation.
super(name, age)
}
study() {
console.log(`I'm studying in grade ${this.grade}.`)
}
}
λ°λΌμ λ€μκ³Ό κ°μ΄ μ μν΄μΌλ§ μλ¬κ° λ°μνμ§ μλλ€.
class Student extends Person {
constructor(name, age, grade) {
super(name, age)
this.name = name
this.age = age
this.grade = grade
}
study() {
console.log(`I'm studying in grade ${this.grade}.`)
}
}
Swift μ Two Phase Initialization μ λ€λ₯Έ μ μ Subclass μμ μ μνλ Properties μμ Superclass μ Constructor λ₯Ό νΈμΆ ν μ΄ν Phase 2μμ ν¨κ» μ μν΄μΌνλ€λ κ²μ΄λ€.
class Student extends Person {
constructor(name, age, grade) {
this.grade = grade
super(name, age)
this.name = name
this.age = age
}
study() {
console.log(`I'm studying in grade ${this.grade}.`)
}
}
λ°λΌμ μμ κ°μ λ¬Έλ² μμ μλͺ»λμλ€.
class Student extends Person {
constructor(name, age, grade) {
super(name, age)
this.name = name
this.age = age
this.grade = grade
}
study() {
console.log(`I'm studying in grade ${this.grade}.`)
}
}
λ°λμ Super μ Constructor λ₯Ό νΈμΆν μ΄ν μ΄λ£¨μ΄μ ΈμΌνλ€!!
5. ES6 Class Private π©βπ»
1. ES6 Class Support Private Properties and Methods
class Counter {
#count = 0
next = function () {
return ++this.#count
}
#reset = function () {
this.#count = 0
}
}
const counter = new Counter()
console.log(counter.next()) // 1
console.log(counter.next()) // 2
console.log(counter.next()) // 3
console.log(counter.count) // undefined
console.log(counter.reset()) // caught TypeError: counter.reset is not a function
Private μΌλ‘ μ μΈλ Properties μ Methods λ μΈλΆμμ μ κ·Όν μ μλ€.
2. ES6 Class Private cannot be hidden
λ¬Έμ λ ν΄λΉ μ΄λ¦μΌλ‘ μ κ·Όμ λ§κ² λ€λ κ²μ΄μ§ μ λ§λ‘ μλνλ₯Ό νλ κ²μ μλλ€.
console.log(counter.count) // undefined
console.log(counter.#count) // caught SyntaxError: Private field '#count' must be declared in an enclosing class
counter.reset() // caught TypeError: counter.reset is not a function
counter.#reset() // caught SyntaxError: Private field '#reset' must be declared in an enclosing class
μλνκ° μλνλ κ² κ°μ§λ§ κ°λ°μκ° μμ±νλ μ½λ μμ± λ°©μμμ private μΌλ‘ μλνλ€λ κ²μ΄μ§ μ λ§λ‘ κ°μ²΄μ Properties μμ²΄κ° hiding λλ κ²μ μλλ€.
console.log(counter) // Counter {#count: 3, #reset: Ζ, next: Ζ}
Closures λ₯Ό μ΄μ©νλ©΄ κ°λ₯νμ§ μμκΉ?
κ°μ²΄λ₯Ό μΆλ ₯νμ λ private μ΄ κ΅¬νλ μ μλ μ μΌν λ°©λ²μ΄λ€. λ¨, Closures λ₯Ό μ¬μ©ν κ°μ²΄ μμ±μ μ¬μ©ν κ²½μ° λ§€λ² μ κ°μ²΄κ° μμ±λλλ° GCκ° μ λλ‘ μλνμ§ μμ Memory Leak μ΄ μκΈΈ μ μλ€κ³ νλ€.
JavaScript μ
built-in objects
μ€ Map, Set, WeakMap, WeakSet λ±μ μ΄μ©νλ λ°©λ²μ μκ°νλ λΈλ‘κ·Έλ μ‘΄μ¬νμ§λ§ λ¨μνdot syntax
λ‘ μ κ·Όμ΄ μ λλ κ² λΏμ΄λ€. μλset
,get
λ©μλλ‘ κ΄λ¦¬νλ κ°μ²΄λ€μ΄λΌ μΌ λΏ private μ΄ μλλ€.
6. Rect Examples π©βπ»
1. ES6 Class Getter/Setter
struct Size {
var width = 0.0, height = 0.0
}
struct Point {
var x = 0.0, y = 0.0
}
struct Rect {
var origin = Point()
var size = Size()
var center: Point {
get {
Point(x: origin.x + (size.width / 2),
y: origin.y + (size.height / 2))
}
set {
origin.x = newValue.x - (size.width / 2)
origin.y = newValue.y - (size.height / 2)
}
}
}
μ μ½λλ₯Ό JavaScript μ ES6 Class λ₯Ό μ΄μ©ν΄ ꡬνν΄λ³΄μ.
class Point {
constructor(x = 0, y = 0) {
this.x = x
this.y = y
}
}
class Size {
constructor(width = 0, height = 0) {
this.width = width
this.height = height
}
}
class Rect {
constructor(origin = new Point(), size = new Size()) {
this.origin = origin
this.size = size
}
get center() {
const centerX = this.origin.x + (this.size.width / 2)
const centerY = this.origin.y + (this.size.height / 2)
return new Point(centerX, centerY)
}
set center(newCenter) {
this.origin.x = newCenter.x - (this.size.width / 2)
this.origin.y = newCenter.y - (this.size.height / 2)
}
}
const square = new Rect(new Point(), new Size(10, 10))
console.log(square.origin) // Point {x: 0, y: 0}
console.log(square.center) // Point {x: 5, y: 5}
square.center = new Point(17.5, 17.5)
console.log('square.origin', square.origin) // Point {x: 12.5, y: 12.5}
console.log('square.center', square.center) // Point {x: 17.5, y: 17.5}
2. Object.defineProperty()
Object.defineProperty()
λ‘ λ°κΏλ³΄μ.
class Rect {
constructor(origin = new Point(), size = new Size()) {
this.origin = origin
this.size = size
Object.defineProperty(this, 'center', {
get: function () {
const centerX = this.origin.x + (this.size.width / 2)
const centerY = this.origin.y + (this.size.height / 2)
return new Point(centerX, centerY)
},
set: function (newCenter) {
this.origin.x = newCenter.x - (this.size.width / 2)
this.origin.y = newCenter.y - (this.size.height / 2)
}
});
}
}
const square = new Rect(new Point(), new Size(10, 10))
console.log(square.origin) // Point {x: 0, y: 0}
console.log(square.center) // Point {x: 5, y: 5}
square.center = new Point(17.5, 17.5)
console.log('square.origin', square.origin) // Point {x: 12.5, y: 12.5}
console.log('square.center', square.center) // Point {x: 17.5, y: 17.5}
3. Use Object.defineProperty() likes Swift extensions
class Rect {
constructor(origin = new Point(), size = new Size()) {
this.origin = origin
this.size = size
}
}
Object.defineProperty(Rect.prototype, 'center', {
get: function () {
const centerX = this.origin.x + (this.size.width / 2)
const centerY = this.origin.y + (this.size.height / 2)
return new Point(centerX, centerY)
},
set: function (newCenter) {
this.origin.x = newCenter.x - (this.size.width / 2)
this.origin.y = newCenter.y - (this.size.height / 2)
}
})
Object.defineProperty()
λ₯Ό Class μ μΈκ³Ό λΆλ¦¬μμΌ Swift μ extensions λ₯Ό μ¬μ©νλ― λΆλ¦¬ν΄ λ€λ£° μ μλ€.
const square = new Rect(new Point(), new Size(10, 10))
console.log(square.origin) // Point {x: 0, y: 0}
console.log(square.center) // Point {x: 5, y: 5}
square.center = new Point(17.5, 17.5)
console.log('square.origin', square.origin) // Point {x: 12.5, y: 12.5}
console.log('square.center', square.center) // Point {x: 17.5, y: 17.5}
4. Use Object.prototype likes Swift extensions
μ 3λ²μ΄ κ°λ₯νλ€λ κ²μ 보μμΌλ prototype μ μ§μ μ΄μ©νλ κ²λ κ°λ₯ν΄λ³΄μΈλ€. κ²°λ‘ λΆν° λ§νμλ©΄ μ΄ λ°©λ²μ μ€ν¨νλ€.
prototype μ μ΄μ©ν νμ₯μ λ¨μν Properties λ Methods μ λλ§ νμ₯μ΄ κ°λ₯νλ€. Getter/Setter
μ κ°μ κ²λ€μ λ±λ‘νλ €λ©΄ λ°λμ
Object.defineProperty()
λ₯Ό μ¬μ©ν΄μΌνλ€.
class Rect {
constructor(origin = new Point(), size = new Size()) {
this.origin = origin
this.size = size
}
}
Rect.prototype.center = {
get: function () {
const centerX = this.origin.x + (this.size.width / 2)
const centerY = this.origin.y + (this.size.height / 2)
return new Point(centerX, centerY)
},
set: function (newCenter) {
this.origin.x = newCenter.x - (this.size.width / 2)
this.origin.y = newCenter.y - (this.size.height / 2)
}
}
const square = new Rect(new Point(), new Size(10, 10))
console.log(square.origin) // Point {x: 0, y: 0}
console.log(square.center) // {get: Ζ, set: Ζ}
square.center = new Point(17.5, 17.5)
console.log('square.origin', square.origin) // Point {x: 0, y: 0}
console.log('square.center', square.center) // Point {x: 17.5, y: 17.5}
Object.prototype
μ μ΄μ©ν λ°©λ²μ Getter/Setter
μ κ°μ κ²λ€μ μ²λ¦¬ν μ μμ΄ μμ κ°μ΄ μμκ³Ό λ¬λ¦¬ μλͺ»λ κ²°κ³Όλ₯Ό λμΆνκ²λλ€.
5. Proxy and Reflect
μ λ‘μ§μ Proxy μ Reflect λ₯Ό μ¬μ©νλ λ°©λ²μΌλ‘ λ³κ²½ν΄λ³΄μ.
class Rect {
constructor(origin = new Point(), size = new Size()) {
this.origin = origin
this.size = size
}
}
const squareProxyHandler = {
get(target, property, receiver) {
switch (property) {
case 'center':
const centerY = target.origin.y + (target.size.height / 2)
const centerX = target.origin.x + (target.size.width / 2)
return new Point(centerX, centerY)
default:
// return Reflect.get(target, property, receiver)
return Reflect.get(...arguments)
}
},
set(target, property, newValue, receiver) {
switch (property) {
case 'center':
target.origin.x = newValue.x - (target.size.width / 2)
target.origin.y = newValue.y - (target.size.height / 2)
break
default:
return Reflect.set(...arguments)
}
}
}
const square = new Rect(new Point(), new Size(10, 10))
const squareProxy = new Proxy(square, squareProxyHandler)
console.log('squareProxy.origin', squareProxy.origin) // Point {x: 0, y: 0}
console.log('squareProxy.center', squareProxy.center) // Point {x: 5, y: 5}
squareProxy.center = new Point(17.5, 17.5)
console.log('squareProxy.origin', squareProxy.origin) // Point {x: 12.5, y: 12.5}
console.log('squareProxy.center', squareProxy.center) // Point {x: 17.5, y: 17.5}
- μ₯μ : Proxy λ₯Ό μ¬μ©νλ©΄ λμΌν ννμ μλ‘ λ€λ₯Έ μΌμ΄μ€λ₯Ό νλμ μ μλ‘ μ¬μ¬μ©ν μ μλ€
- λ¨μ : Reflection μ λΉμ©μ΄ λ§μ΄ λλ λΉμ¦λμ€ λ‘μ§μ΄κ³ μ½λλμ΄ λμ΄λλ€.