개발

크록포드 스타일 자바스크립트 오브젝트 (Crokford Style Javascript Ojbect)

동고킴 2022. 9. 7. 22:53
반응형

크록포드(Crockford) 스타일로 자바스크립트 오브젝트 생성하기


자바스크립트는 자바처럼 전통적인 객체지향언어가 아니며 객체 지향 기능을 갖춘 프로토타입 기반 언어로 간주된다. (비록 다른 객체지향 언어들과의 차이점에 대한 논쟁이 있긴 하지만, 자바스크립트는 강력한 객체지향 프로그래밍 능력을 지니고 있다)

프로토타입 기반 프로그래밍은 클래스가 필요없는 객체지향 프로그래밍 스타일로 프로토타입 체인과 클로저 등으로 객체 지향 언어의 상속, 캡슐화(정보 은닉) 등의 개념을 구현할 수 있다. 자바스크립트에서 객체를 다양한 방법으로 생성할 수 있는데, 크록포드는 객체를 어떤 스타일로 만드는지 살펴봤다.

더글라스 크록포드(Douglas Crockford)는 자바스크립트의 아버지로 불리는 미국의 개발자이다. 자바스크립트 언어 개발에 참여하였고 JSON 데이터 포맷을 보급하였으며 JSLint, JSMine 등 다양한 자바스크립트 관련 도구들을 개발하기도 하였다.

더글라스 크록포드


크록포드 스타일 객채 생성을 살펴보기 전에 먼저 1) 오리지널 자바스크립트 스타일과 2) 클래스 스타일로 객체를 만들어본 후에 3) 크록포드 스타일 객체를 만들어보겠다.

1) Original Javascript Type Object

오리지널 자바스크립트 객체는 아래처럼 만들수 있다.

function Person(firstName, lastName, age) {
  this.firstName = firstName;
  this.lastName = lastName;
  this.age = age;
  return this;
}

const person = new Person("John", "Smith", 30);
console.log(person);
// Person { firstName: 'John', lastName: 'Smith', age: 30 }


prototype을 이용하여 Person 객체에 속성과 함수를 추가할 수 있다.

function Person(firstName, lastName, age) {
  this.firstName = firstName;
  this.lastName = lastName;
  this.age = age;
  return this;
}

Person.prototype.getFullName = function () {
  return `${this.firstName} ${this.lastName}`;
};

Person.prototype.description = function () {
  console.log(`${this.firstName} ${this.lastName} is ${this.age} years old.`);
};

const person = new Person("John", "Smith", 30);
console.log(person.getFullName());
person.description();

// John Smith
// John Smith is 30 years old.

2) Class Style Object

ES6에 클래스가 추가되었다. ES6의 클래스는 기존 프로토타입 기반 객체지향 프로그래밍보다 단순 명료한 새로운 문법을 제시한다. MDN에서 클래스는 객체 생성을 위한 템플릿이라고 설명하고 있다.

MDN
class Person {
  constructor(firstName, lastName, age) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
  }

  getFullName() {
    return `${this.firstName} ${this.lastName}`;
  }

  description() {
    console.log(`${this.firstName} ${this.lastName} is ${this.age} years old.`);
  }
}

const person = new Person("John", "Smith", 30);
console.log(person.getFullName());
person.description();

// John Smith
// John Smith is 30 years old.

3) Crockford Style Object

크록포드는 객체를 정의하기 위해 'class' 키워드나 'prototype' 속성이 필요하지 니다. 또한 새 개체를 인스턴스화 하기 위해 'new' 키워드를 사용할 필요가 없다.

function createPerson(firstName, lastName, age) {
  function getFullName() {
    return `${this.firstName} ${this.lastName}`;
  }

  function description() {
    console.log(`${this.firstName} ${this.lastName} is ${this.age} years old.`);
  }

  return {
    firstName,
    lastName,
    age,
    getFullName,
    description,
  };
}

const person = createPerson("John", "Smith", 30);
console.log(person.getFullName());
person.description();

//John Smith
// John Smith is 30 years old.

크록포드 객체는 팩토리 함수로 정의된다. 위의 예에는 내부 함수가 있는 함수가 있다. 'getFullName' 함수는 클로저이다. 자바스크립트의 클로저는 상위 함수의 모든 매개변수에 액세스 할 수 있으므로 'firstName', 'lastName', 'age' 속성에 액세스할 수 있다.

The Better Parts. Douglas Crockford. JS Fest 2018에서 크록포드가 논의한 것 중 하나는 정의 함수에 대한 생성자 매개변수를 정의하는 방법이다. 그는 하나의 단일 객체를 함수에 전달할 것을 제안했다. 자바스크립트를 사용하면 함수에 원하는 만큼 많은 매개변수를 전달할 수 있다. 만약 단일 객체를 사용하지 않았다면, 함수에 매개변수를 추가할 때 해당 함수를 호출하는 코드의 모든 위치를 리팩토링 해야 한다.

function createPerson(params) {
  const { firstName, lastName, age } = params;

  function getFullName() {
    return `${this.firstName} ${this.lastName}`;
  }

  function description() {
    console.log(`${this.firstName} ${this.lastName} is ${this.age} years old.`);
  }

  return {
    firstName,
    lastName,
    age,
    getFullName,
    description,
  };
}

const params = {
  firstName: "John",
  lastName: "Smith",
  age: 30,
};

const person = createPerson(params);
console.log(person.getFullName());
person.description();

// John Smith
// John Smith is 30 years old.

생성자 매개변수로 단일 객체를 사용하는 방식의 좋은 점 중 하나는 구조 분해 할당(Destructuring assignment)을 사용하여 매개변수의 특정 값을 가져올 수 있다는 것이다. 또한 매개변수의 순서도 중요하지 않게된다. 생성자 매개변수로 객체 리터럴을 사용할 때 속성을 임의의 순서로 배치할 수 있다.

function createPerson(params) {
  const { firstName, lastName, age } = params;

  //...//

  return Object.freeze({
    firstName,
    lastName,
    age,
    getFullName,
    description,
  });
}


그리고 필요에 따라 위처럼 'Object.freeze' 함수를 사용하여 함수를 정의한 후 이 객체의 프로토타입에 속성과 함수가 추가되는 것을 방지하면 된다.


https://www.youtube.com/watch?v=XFTOG895C7c


https://www.youtube.com/watch?v=CeZyDDsrQWk

반응형