이전에 ES6 있었 혼란을 많이 사이의 차이점에 대해 공장 기능과 생성 기능에서 JavaScript. ES6 에는`class`키워드가 있기 때문에 많은 사람들이 생성자 함수에 대한 많은 문제를 해결했다고 생각하는 것 같습니다. 아직 알아야 할 주요 차이점을 살펴 보겠습니다.,
첫째,예를 살펴 보자의 각
각 이러한 전략의 저장 방법에 공유 프로토 타입 선택적으로 지원하는 개인을 통해 데이터 생성자의 기능을 마감. 다른 말로하면,그들은 대부분 동일한 특징을 가지고 있으며,대부분 상호 교환 적으로 사용될 수있다.
JavaScript 에서 모든 함수는 새 객체를 반환 할 수 있습니다. 생성자 함수 또는 클래스가 아닌 경우 팩토리 함수라고합니다.,
ES6 클래스 desugar 을 생성 함수,그래서 모든 것에 대해 다음과 생성 기능도 적용됩니다 ES6 클래스:
class Foo {}console.log(typeof Foo); // function
생성자력 발신자가 사용하는new
키워드를 사용합니다. 공장에서는 그렇지 않습니다.그게 다야,하지만 그건 몇 가지 관련 부작용이 있습니다.
그렇다면new
키워드는 무엇을합니까?,
참고:우리는이 사용
instance
을 참조하여 새로 만들어진 인스턴스Constructor
를 참조하시 기능 또는 생성자를 만든 클래스의 인스턴스입니다.
- 는 새 인스턴스 객체를 인스턴스화하고 생성자 내에서
this
를 바인딩합니다. - 는
instance.__proto__
를Constructor.prototype
에 바인딩합니다. - 2 의 부작용으로
instance.__proto__.constructor
를Constructor
에 바인딩합니다., - 는 암시 적으로
this
를 반환하며,이는instance
를 나타냅니다.
생성자의 장점&`class`
- 대부분의 책은 클래스 또는 생성자를 사용하도록 가르칩니다.
this
는 새 객체를 나타냅니다.- 어떤 사람들은
myFoo = new Foo()
가 읽는 방식을 좋아합니다. - 이 있을 수 있습 마이크로 최적화 성능을,하지만 당신은 그것에 대해 걱정하지 않는 한 당신이 프로파일 된 코드를 입증하는 문제 있습니다.,
생성자의 단점&`class`
ES6 이전에new
는 매우 일반적인 버그였습니다. 응하는,그것을 많은 사람들이 사용한 보일러를 적용하다:
function Foo() {
if (!(this instanceof Foo)) { return new Foo(); }
}
에 ES6+(ES2015)하려고 하면 클래스 생성자를 호출하지 않고new
항상 던져 오류가 있습니다. 그것은 가능하지 않지new
요구 사항에서 호출자가 포장 없이 귀하의 클래스는 공장에서 함수입니다.,
인스턴스화의 세부 사항은 호출 API 로 유출됩니다(`새`요구 사항을 통해).
모든 호출자는 생성자 구현에 단단히 결합됩니다. 혹시 공장의 추가 유연성을 필요로하는 경우,리팩터링은 깨는 변화이다. Class to factory refactor 는 Martin Fowler,Kent Beck,John Brant,William Opdyke 및 Don Roberts 의 정액 리팩토링 책인”리팩토링:기존 코드 디자인 개선”에 나타날 정도로 일반적입니다.,
생성자를 끊을 공개/비공개 원칙
기 때문에new
요구 사항,생성 함수 위반 open/closed 원리:API 확장을위한 열려 있어야 하지만 닫을 위해 수정할 수 있습니다.
나고 주장하는 클래스를 공장 리팩터링은 일반적인 충분히 고려해야 하는 표준 확장을 위해 모든 생성자:서 업그레이드 클래스를 공장되지 않아야 합 것들,그러나 자바스크립트,그것은 않습니다.,
시작하는 경우 밖으로 내보내 생성자 또는 클래스고 사용자 시작하자를 사용하여,다음을 아래로 당신은 당신의 유연성,공장(예를 들어,스위치를 구현하는 객체 사용 수영장,또는 인스턴스화에 실행 상황,또는 더 상속성하는 다른 프로토타입),당신은 쉽게 수 없습니다 그렇게 하지 않고 강제로 리팩터에 연결이 필요합니다.,
불행하게도,자바 스크립트에서의 전환에서 생성자 또는 클래스를 공장이는 것은 주요 변경 내용입니다:
위의 예에서,우리는 우리 밖으로 시작하는 클래스,하지만 우리가 원하는 기능을 추가하 제공하는 다른 종류의 차 번들. 그렇게하기 위해 공장은 다른 자동차 번들에 대한 대체 프로토 타입을 사용합니다. 내가 사용했던 이 기술을 저장하는 다양한 구현에서의 미디어 플레이어 인터페이스,쑤 정확한 시제품에 기반한 종류의 미디어 플레이어 필요하 제어합니다.,
를 사용하여 생성자할 수 있게 거짓이`다른`
중 하나의 주요 변경 사항에 대해 생성자를 공장 리팩터링은instanceof
. 때때로 사람들은 코드에서instanceof
를 유형 검사 가드로 사용하려는 유혹을받습니다. 그것은 매우 문제가 될 수있다. 나는 당신이instanceof
를 피하는 것이 좋습니다.나는 이것이 내가 할 수있는 유일한 방법이라고 생각한다.,
instanceof
하지 않는 유형을 확인하는 방법으로 당신은 기대와 유사 검사에서 할 강력한 언어입니다. 대신 객체의__proto__
객체를Constructor.prototype
속성과 비교하는 id 검사를 수행합니다.
예를 들어 iframe 과 같은 다른 메모리 영역에서 작동하지 않습니다(타사 JavaScript 내장 버그의 일반적인 소스). 또한Constructor.prototype
가 대체되면 작동하지 않습니다.,
그것은 또한 실패는 경우 밖으로 시작하는 클래스 또는 생성(반환하는this
,연결된Constructor.prototype
)다음 스위치를 내보내는 임의의체(에 연결되지 않는Constructor.prototype
)는 무엇이 일어나 변경할 때부터 생성자를 공장이 있습니다.
요컨대,instanceof
는 생성자에서 팩토리로의 전환이 중단되는 또 다른 방법입니다.
클래스 사용의 이점
- 편리하고 자체 포함 된 구문.,
- 자바 스크립트에서 클래스를 에뮬레이트하는 단일 정식 방법. ES6 이전에는 인기있는 라이브러리에서 몇 가지 경쟁 구현이있었습니다.
- 클래스 기반 언어 배경의 사람들에게 더 친숙합니다.
의 단점은 클래스를 사용하는
모든 생성자의 단점이 있다.
- 유혹하는 사용자를 위해 만들 문제가 있는 클래스 계층구조를 사용하는
extends
키워드를 사용합니다.,
클래스 계층으로 이어질 무리의 잘 알려진 문제에 객체 지향적 디자인 등 취약한 기본 클래스 문제,고릴라 바나나는 문제로,복제 필요성에 의하여,문제가 및니다. 불행 하 게도,클래스 affords 공 던지기 여유 처럼 확장 하 고 자 앉아 여유. 자세한 내용은”JavaScript 의 두 기둥:프로토 타입 OO”와”Dev Team Death Spiral 내부”를 읽으십시오.,
는 점은 주목할 만한 가치가 있 모두 생성자 및 공장하는 데 사용될 수도 있습 만들기 문제가 있속 계층 구조이지만,함께`연장`키워드로,클래스를 만듭제에 이르는 당신이 잘못된 경로를 아래로. 다시 말해서,그것은 당신을 권장합에서 생각하는 용어의 유연성(자주 잘못된)입니다-관계보다 더 유연한 작곡가-a 또는 할 수 있다는 관계입니다.
affordance 는 특정 작업을 수행 할 수있는 기회를 제공하는 기능입니다., 예를 들어,손잡이를 가르치시 비틀림,레버를 제공한 당기,버튼을 준 누르,등등….
의 혜택을 사용하여 공장
공장은 훨씬 더 유연한 보수 또는 클래스들을 지도하지 않는 사람들이 잘못된 경로를 아래로써 그들을 유혹하는`연장`키워드가 깊은 상속의 계층 구조입니다. 함수 및 모듈을 포함하여 클래스 상속보다 선호해야하는보다 안전한 코드 재사용 메커니즘이 많이 있습니다.,
반환 모든 임의의 개체와 사용하여 임의의 프로토타입
예를 들어,당신은 쉽게 만들 수 있습니다 다양한 유형의 객체를 구현하는 동일한 API,예를 들면,미디어 선수는 인스턴스화할 수 있습니다 플레이어를 위한 여러 형태의 비디오 컨텐츠 사용하는 다른 Api 후드,또는 이벤트 라이브러리를 방출할 수 있습니다 DOM 이벤트 또는 웹 소켓 이벤트입니다.
공장할 수 있습 또한 객체를 인스턴스화에 실행 상황을 활용하는 개체의 수영장을 위한 가동 가능한 prototypal 상속 모델입니다.,
리팩토링은 걱정하지 않습니다
팩토리에서 생성자로 변환 할 필요가 없으므로 리팩토링은 결코 문제가되지 않습니다.
No`new`
new
사용에 대한 모호성이 없습니다. 그렇지 않습니다.(this
가 나쁘게 행동하게 만들 것입니다,다음 지점 참조).
표준`이`동작
this
동작으로 일반적으로,그래서 당신은 그것을 사용할 수 있습 액세스는 부모 개체입니다. 예를 들어 안에player.create()
,this
말레이어,다른 어떤 메소드 호출합니다., call()
및apply()
도 할당this
으로 예상된다.
어떤 사람들은`myFoo=createFoo()`가
- 를 읽는 방식을 좋아하지만 인스턴스에서
Factory.prototype
에 대한 링크를 만들지 않습니다. 대신instanceof
는 항상 실패합니다. 혜택을 참조하십시오. this
는 팩토리 내부의 새 객체를 참조하지 않습니다. 혜택을 참조하십시오.,- 마이크로 최적화 벤치 마크에서 생성자 함수보다 느리게 수행 할 수 있습니다. 느린 경로는 여전히 매우 빠릅니다—오래된 컴퓨터에서 수백만 개의 ops/sec. 이것은 응용 프로그램 코드보다 라이브러리 또는 프레임 워크 코드에서 우려 될 가능성이 큽니다. 마이크로 최적화를 사용하기 전에 항상 사용자 관점에서 벤치마킹하십시오.
결론
In my opinion,class
수 있는 편리한 구문,하지만 할 수 없다는 사실 때문에 그것을 미끼는 부주의한 사용에 충돌하는 바위의 클래스를 상속입니다., 그것은 또한 위험에 있기 때문에,미래를 업그레이드해야 할 수 있습을 공장이 있지만,모든 수출될 것이 단단히 결합되어 생성자 기능 때문에new
키워드는 사실을에서 이동 클래스를 공장이 깨 변경합니다.
할 수 있다는 생각에 그냥 리팩터링을 호출이 있지만,큰 팀,또는 하드 디스크 드라이브가와 함께 작업의 일부는 공개 API,당신은 휴식하는 코드에 있지 않습니다. 즉,호출자를 리팩토링하는 것도 옵션이라고 항상 가정 할 수는 없습니다.,
좋은 점에 대해 공장은 그들이 단지 더 강력하고 더 많은 유연하게,그들은 또한 가장 쉬운 방법을 격려하는 전체 팀,그리고 전체 API 는 사용자 기초를 사용하는 패턴을,간단한 유연하고 안전합니다.피>