자바 스크립트 팩토리 함수 vs 생성자 함수 vs 클래스

ES6 이전에는 자바 스크립트에서 팩토리 함수와 생성자 함수의 차이점에 대해 많은 혼란이있었습니다. ES6에는 `class` 키워드가 있기 때문에 많은 사람들이 생성자 함수의 많은 문제를 해결했다고 생각하는 것 같습니다. 그렇지 않았습니다. 여전히 알아야 할 주요 차이점을 살펴 보겠습니다.

먼저 각각의 예를 살펴 보겠습니다.

각 전략은 공유 프로토 타입에 메서드를 저장하고 선택적으로 생성자 함수 클로저를 통해 개인 데이터를 지원합니다. 즉, 거의 동일한 기능을 가지고 있으며 대부분 서로 바꿔서 사용할 수 있습니다.

자바 스크립트에서 모든 함수는 새 개체를 반환 할 수 있습니다. 생성자 함수 나 클래스가 아닌 경우 팩토리 함수라고합니다.

ES6 클래스는 생성자 함수로 탈당하므로 생성자 함수에 대해 따르는 모든 내용은 ES6 클래스에도 적용됩니다.

공장과 건설자의 차이점은 무엇입니까?

생성자는 호출자가 new 키워드를 사용하도록합니다. 공장은 그렇지 않습니다. 그게 다입니다.하지만 여기에는 몇 가지 관련 부작용이 있습니다.

new 키워드는 무엇을합니까?

참고 : 새로 생성 된 인스턴스를 참조하기 위해 instance 를 사용하고 인스턴스를 생성 한 생성자 함수 또는 클래스를 참조하기 위해 Constructor 를 사용할 것입니다.

생성자의 이점 & amp; `클래스`

생성자의 단점 & amp; `클래스`

1. `new`가 필요합니다.

ES6 이전에는 new 를 잊어 버리는 것이 매우 흔한 버그였습니다. 이에 대응하기 위해 많은 사람들이 상용구를 사용하여 시행했습니다.

ES6 + (ES2015)에서 new 없이 클래스 생성자를 호출하려고하면 항상 오류가 발생합니다. 클래스를 팩토리 함수로 래핑하지 않으면 호출자에게 새로운 요구 사항을 강제하는 것을 피할 수 없습니다.

2. 인스턴스화의 세부 사항은 ‘new’요구 사항을 통해 호출 API로 유출됩니다.

모든 호출자는 생성자 구현과 밀접하게 연결됩니다. 공장의 추가적인 유연성이 필요한 경우 리팩터링은 획기적인 변경 입니다. Class to Factory 리팩터링은 Martin Fowler, Kent Beck, John Brant, William Opdyke 및 Don Roberts의 “Refactoring : Improving the Design of Existing Code”라는 주요 리팩토링 책에 나타날 정도로 충분히 일반적입니다.

3. 생성자는 개방 / 폐쇄 원칙을 위반합니다.

새로운 요구 사항으로 인해 생성자 함수는 개방 / 폐쇄 원칙을 위반합니다. API는 확장을 위해 개방 이어야하지만 닫힘 .

클래스에서 팩토리로 리팩터링하는 것은 모든 생성자에 대한 표준 확장으로 간주되어야 할만큼 충분히 일반적이라고 주장합니다. 클래스에서 팩토리로 업그레이드하면 문제가 발생하지 않지만 JavaScript에서는 그렇습니다.

생성자 또는 클래스 내보내기를 시작하고 사용자가 생성자를 사용하기 시작하면 길을 따라 가면서 공장의 유연성이 필요하다는 것을 알게됩니다 (예 : 개체 풀을 사용하도록 구현을 전환하거나 실행 컨텍스트 또는 대체 프로토 타입을 사용하여 상속 유연성을 높이려면 호출자에게 리팩터링을 강요하지 않으면 쉽게 수행 할 수 없습니다.

안타깝게도 자바 스크립트에서 생성자 또는 클래스에서 팩토리로 전환하는 것은 획기적인 변경 입니다.

위의 예에서는 클래스로 시작하지만 다양한 종류의 자동차 번들을 제공하는 기능을 추가하려고합니다. 이를 위해 공장은 다른 자동차 번들에 대한 대체 프로토 타입을 사용합니다. 저는이 기술을 사용하여 미디어 플레이어 인터페이스의 다양한 구현을 저장하고 플레이어가 제어하는 ​​데 필요한 미디어 유형에 따라 올바른 프로토 타입을 선택했습니다.

4. 생성자를 사용하면기만적인`instanceof` 가능

팩토리 리팩터링에 대한 생성자의 주요 변경 사항 중 하나는 instanceof 입니다. 때때로 사람들은 유형 검사 가드로 instanceof 를 사용하려는 유혹을받습니다. 그들의 코드에서. 그것은 매우 문제가 될 수 있습니다. instanceof 를 사용하지 않는 것이 좋습니다.

`거짓말`사례

instanceof 는 강력한 유형의 언어에서 유사한 검사가 수행 될 것으로 예상하는 방식으로 유형 검사를 수행하지 않습니다. 대신 개체의 __ proto __ 개체를 Constructor.prototype 속성과 비교하여 ID 확인을 수행합니다.

예를 들어 iframe과 같은 다른 메모리 영역에서 작동하지 않습니다 (타사 자바 스크립트 삽입의 일반적인 버그 소스). Constructor.prototype 이 교체 된 경우에도 작동하지 않습니다.

클래스 또는 생성자 ( Constructor.prototype 에 연결된 this 를 반환)로 시작한 다음 임의의 내보내기로 전환하는 경우에도 실패합니다. 객체 ( Constructor.prototype 에 연결되지 않음)는 생성자에서 팩토리로 변경할 때 발생합니다.

요컨대, instanceof 는 생성자에서 팩토리로의 전환이 파괴적인 변경 인 또 다른 방법입니다.

수업 이용의 장점

클래스 사용의 단점

모든 생성자 단점 및 다음 사항 추가 :

클래스 계층 구조는 깨지기 쉬운 기본 클래스 문제, 고릴라 바나나 문제, 필요에 의한 중복 문제 등을 포함하여 객체 지향 설계에서 잘 알려진 문제로 이어집니다. 불행히도, 수업은 공처럼 확장되어 던질 수 있고 의자는 앉을 수 있습니다. 자세한 내용은 “JavaScript의 두 기둥 : 프로토 타입 OO”및 “Inside the Dev Team Death Spiral”을 읽어보십시오.

생성자와 팩토리를 모두 사용하여 문제가있는 상속 계층 구조를 만들 수도 있지만 `extends` 키워드를 사용하면 클래스가 잘못된 경로로 안내하는 어포던스를 생성합니다. 즉,보다 유연한 구성 has-a 또는 보다는 유연하지 않은 (그리고 종종 틀린) is-a 관계의 관점에서 생각하도록 권장합니다. 할 수있는 관계.

어포던스 는 특정 작업을 수행 할 기회를 제공하는 기능입니다. 예를 들어 손잡이는 비틀기, 레버는 당기기, 버튼은 누르기 등을 가능하게합니다.

공장 이용의 이점

팩토리는 생성자 함수 나 클래스보다 훨씬 더 유연하며 `extends` 키워드와 깊은 상속 계층 구조로 사람들을 유혹하여 잘못된 길로 안내하지 않습니다. 함수와 모듈을 포함하여 클래스 상속보다 선호해야하는 더 안전한 코드 재사용 메커니즘이 많이 있습니다.

1. 임의의 객체를 반환하고 임의의 프로토 타입을 사용합니다.

예를 들어, 동일한 API를 구현하는 다양한 유형의 객체를 쉽게 만들 수 있습니다. 예를 들어 내부적으로 서로 다른 API를 사용하는 여러 유형의 동영상 콘텐츠에 대해 플레이어를 인스턴스화 할 수있는 미디어 플레이어 또는이를 내보낼 수있는 이벤트 라이브러리 DOM 이벤트 또는 웹 소켓 이벤트.

팩토리는 또한 실행 컨텍스트에서 개체를 인스턴스화하고 개체 풀을 활용하며보다 유연한 프로토 타입 상속 모델을 허용 할 수 있습니다.

2. 리팩토링 걱정 없음

공장에서 생성자로 전환 할 필요가 없으므로 리팩토링이 문제가되지 않습니다.

3. `new`

없음

new 사용에 대해 모호하지 않습니다. 하지 마십시오. (가 제대로 작동하지 않습니다. 다음 요점을 참조하십시오.)

4. 표준 `this` 동작

this 는 정상적으로 작동하므로 상위 개체에 액세스하는 데 사용할 수 있습니다. 예를 들어 player.create () 내부에서 this 는 다른 메서드 호출과 마찬가지로 플레이어를 나타냅니다. call () apply () 도 예상대로 this 를 다시 할당합니다.

5. 기만적인 `instanceof`

없음

6. 어떤 사람들은`myFoo = createFoo ()`가 읽는 방식을 좋아합니다

공장의 단점

결론

내 생각에 class 는 편리한 구문을 가지고있을 수 있지만, 그것은 부주의 한 사용자가 클래스 상속의 바위에 충돌하도록 유인한다는 사실을 보완 할 수 없습니다. 또한 미래에 팩토리로 업그레이드하고 싶을 수 있지만 모든 호출자는 new 키워드와 클래스에서 팩토리로 이동한다는 사실 때문에 생성자 함수와 밀접하게 연결되기 때문에 위험합니다. 획기적인 변화입니다.

호출 사이트 만 리팩터링 할 수 있다고 생각할 수 있지만 대규모 팀에서는 작업중인 클래스가 공개 API의 일부인 경우 제어 할 수없는 코드를 손상시킬 수 있습니다. 즉, 호출자를 리팩토링하는 것이 옵션이라고 항상 가정 할 수는 없습니다.

공장의 멋진 점은 공장이 더 강력하고 유연 할뿐만 아니라 전체 팀과 전체 API 사용자 기반이 간단하고 유연하며 안전한 패턴을 사용하도록 장려하는 가장 쉬운 방법이라는 것입니다.

실시간 1 : 1 멘토링으로 기술 수준 향상

DevAnywhere는 고급 자바 스크립트 기술 수준을 높이는 가장 빠른 방법입니다.

Eric Elliott “Programming JavaScript Applications” (O’Reilly)의 작성자입니다. , DevAnywhere.io 의 공동 설립자입니다. 그는 Adobe Systems , Zumba Fitness , 월스트리트 저널 , ESPN , BBC Usher , 프랭크 오션 , 메탈리카 등.

그는 세상에서 가장 아름다운 여성과 원하는 곳에서 일합니다.