>  기사  >  웹 프론트엔드  >  JavaScript 객체 생성 패턴 및 모범 사례

JavaScript 객체 생성 패턴 및 모범 사례

黄舟
黄舟원래의
2017-02-23 13:48:31917검색

JavaScript에서 "객체 생성"은 복잡한 주제입니다. 이 언어는 객체를 생성하는 다양한 방법을 제공하므로 초보자와 숙련된 사용자 모두 어떤 것을 선택해야 할지 혼란스러울 수 있습니다. 그러나 객체를 생성하는 방법은 다양하고 구문도 매우 다르게 보일 수 있지만 실제로는 생각보다 더 유사할 수 있습니다. 이 기사에서는 객체 생성 방법을 분류하고 다양한 방법 간의 종속성과 점진적인 관계를 밝히는 여정을 안내합니다.

객체 리터럴

첫 번째 단계는 의심할 여지 없이 객체, 즉 객체 리터럴을 생성하는 가장 간단한 방법입니다. JavaScript는 클래스, 템플릿, 프로토타입 없이 "무에서" 객체를 생성할 수 있으며 메서드와 데이터가 있는 객체인 "팝"이 나타날 수 있다고 항상 설교합니다.

var o = {
  x: 42,
  y: 3.14,
  f: function() {},
  g: function() {}
};

그러나 이 방법에는 단점이 있습니다. 동일한 유형의 객체를 다른 곳에서 생성하려면 이 객체의 메소드, 데이터 및 초기화를 복사하여 붙여넣어야 합니다. 동일한 유형의 객체를 하나만 생성하는 대신 일괄적으로 생성하는 방법이 필요합니다.

팩토리 기능

다음 단계는 팩토리 기능입니다. 분명히 이 방법을 사용하여 동일한 구조, 인터페이스 및 구현을 가진 개체 클래스를 만드는 것이 가장 쉽습니다. 객체 리터럴을 직접 생성하지 않고 객체 리터럴을 함수의 반환 값으로 사용합니다. 동일한 유형의 객체를 여러 번 또는 여러 위치에 생성해야 하는 경우 이 함수를 호출하기만 하면 됩니다.

function thing() {
  return {
    x: 42,
    y: 3.14,
    f: function() {},
    g: function() {}
  };
}

var o = thing();

그러나 이 접근 방식에는 단점도 있습니다. 즉, 각 개체에 팩토리 함수의 독립적인 복사본이 포함되어 있기 때문에 메모리 팽창이 발생한다는 것입니다. 이론적으로 우리는 모든 객체가 팩토리 기능의 복사본을 공유하기를 원합니다.

프로토타입 체인

JavaScript는 프로토타입 체인이라고 하는 객체 간 데이터 공유를 위한 내장 메커니즘을 제공합니다. 개체의 속성에 액세스하면 요청을 완료하기 위해 다른 개체에 위임됩니다. 이를 사용하여 생성된 각 개체에 고유한 데이터만 포함하고 다른 속성에 대한 요청은 모두 프로토타입 체인의 공통 개체에 위임되도록 팩토리 함수를 수정할 수 있습니다.

var thingPrototype = {
  f: function() {},
  g: function() {}
};

function thing() {
  var o = Object.create(thingPrototype);

  o.x = 42;
  o.y = 3.14;

  return o;
}

var o = thing();

사실 JavaScript 자체에는 이러한 일반적인 패턴을 지원하는 메커니즘이 내장되어 있습니다. 우리는 이 공유 객체(즉, 프로토타입 객체)를 직접 생성할 필요가 없습니다. JavaScript는 각 함수에 대한 프로토타입 객체를 자동으로 생성하며 이 객체에 직접 공유 데이터를 넣을 수 있습니다.

아아아아

그러나 이 방법에는 단점도 있습니다. 즉, 중복이 발생한다는 것입니다. 위의 함수의 첫 번째 줄과 마지막 줄은 모든 "대리자 프로토타입의 팩토리 함수"에서 거의 차이 없이 반복됩니다.

ES5 클래스

반복되는 코드를 추출하여 사용자 정의 함수에 넣을 수 있습니다. 이 함수는 객체를 생성하고 다른 임의의 함수(매개변수 함수)의 프로토타입과 위임(상속) 관계를 설정합니다. 그런 다음 새로 생성된 객체를 매개변수로 사용하고 이 함수(매개변수 함수)를 호출하고 마지막으로 이것을 반환합니다. 새로운 개체.

thing.prototype.f = function() {};
thing.prototype.g = function() {};

function thing() {
  var o = Object.create(thing.prototype);

  o.x = 42;
  o.y = 3.14;

  return o;
}

var o = thing();

사실 JavaScript에도 이 방법이 내장되어 있습니다. 우리가 정의한 create 함수는 실제로 new 키워드의 기본 구현이므로 create를 new로 쉽게 대체할 수 있습니다.

function create(fn) {
  var o = Object.create(fn.prototype);

  fn.call(o);

  return o;
}

// ...

Thing.prototype.f = function() {};
Thing.prototype.g = function() {};

function Thing() {
  this.x = 42;
  this.y = 3.14;
}

var o = create(Thing);

우리가 도착한 역은 흔히 ES5 클래스라고 불린다. 함수를 통해 객체를 생성하고, 공유해야 할 데이터를 프로토타입 객체에 위임하고, new 키워드를 사용하여 반복되는 논리를 처리합니다.

그러나 이 방법에는 단점도 있습니다. 장황하고 보기 흉하며 상속을 구현할 때 더욱 장황하고 보기 흉해집니다.

ES6 类

JavaScript最新的相关改进是ES6 类,用新语法来实现上述功能要简洁得多。

class Thing {
  constructor() {
    this.x = 42;
    this.y = 3.14;
  }

  f() {}
  g() {}
}

var o = new Thing();

比较

多年以来,JavaScript开发者们与原型链的关系总是若即若离,纠缠不清。而今天我们最有可能遇到的两种创建对象的方式,一种是强烈依赖原型链的class语法,另一种则是完全不依赖原型链的工厂函数语法。这两种方式在性能上和特点上是不一样的——尽管差别不太大。

性能

今天的JavaScript引擎已经经过了大幅度的优化,以至于很难通过JavaScript代码来推断怎样会比较快。关键在于测量方法。然而测量方法有时也会失灵。通常每六周就会有更新的JavaScript引擎发布,而在这之前采取的测量方法,和基于这种测量方法做出的决策都有可能失去意义。因此,我的经验法则是选择最官方、最广泛使用的语法,因为大多数时候它经历的实践检验最多,因而性能是最高的。目前来说class语法最符合这一点,在我写这篇文章时,class语法大约比返回字面量的工厂函数快3倍。

特点

随着ES6的发布,类与工厂函数之间曾经存在的几点差异消失了。现在,工厂函数和类都能够强制实现真正的私有数据——工厂函数通过闭包实现,类通过WeakMap实现。两者都能实现多重继承——工厂函数可以将其他属性混入自己的对象,类也可以将其他属性混入自己的原型,或者通过类工厂,通过代理也能实现。工厂函数和类也都可以在需要的时候返回任意对象,语法也都很简单。

结论

综合考虑,我更倾向于class语法。它标准、简单、干净、快速,还提供了所有曾经只有函数工厂才具备的特点。

 以上就是JavaScript 创建对象模式与最佳实践的内容,更多相关内容请关注PHP中文网(www.php.cn)! 


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.