The factory method, constructor, and class in JavaScript
This article is reproduced from: Zhongcheng translation
Translator: Cheuchen
Links: http://www.zcfy.cc/article/1129
Original: https://medium.com/javascript-scene/ Javascript-factory-functions-vs-constructor-functions-vs-classes-2f22ceddf33e#.wby148xu6
Before the advent of ES6, people often wondered what the difference was between the factory pattern and the constructor pattern in JavaScript. The _ keyword is presented in ES6 class
, which many people think solves many of the problems in the constructor pattern. In fact, the problem has not been solved. Let's look at some important differences between the factory pattern, the constructor pattern, and class
_.
First, let's take a look at these three ways of example:
//ClassclassClasscar{ Drive(){ Console.Log(' vroom! '); }}ConstCar1= New Classcar();Console.Log(car1. Drive());//Constructor (constructor mode)function Constructorcar(){}Constructorcar.prototype. Drive = function(){ Console.Log(' vroom! ');};ConstAa02= New Constructorcar();Console.Log(car2. Drive());//Factory (Factory mode)ConstProto= { Drive(){ Console.Log(' vroom! '); }};function Factorycar(){ return Object.Create(Proto);}ConstCar3= Factorycar();Console.Log(Car3. Drive());
These methods store the method in a shared prototype and then selectively support private data through the closure of the constructor. In other words, they almost have the same characteristics, so they can often be used interchangeably.
> in JavaScript, any function can return a new object. When this function is not a constructor or _ class
_, it is called a factory function.
The _ _ In the ES6 class
is actually the syntactic sugar of the constructor, so it has all the advantages and disadvantages of the constructor function:
class Foo {}
console.log(typeof Foo); // function
Constructors and _
class
_ The advantages
- Most books Teach _
class
_ or constructor functions.
- _
this
_ points to the new object.
- Some people like _ _
myFoo = new Foo()
this notation.
- Constructors and _
class
_ have many minor optimizations, but unless you have analyzed the code quantitatively, and these optimizations are really important to the performance of the program, this should not be considered.
Constructors and _
class
_ Disadvantages of 1. Need
new
Before ES6, the omission of _ new
_ _ is a common bug. In order to deal with it, many people use the following methods:
function Foo() { if (!(this instanceof Foo)) { return new Foo(); }}
In ES6 (ES2015), if you attempt to invoke the class constructor without using _ new
, an error will be thrown. It is only possible to avoid having to use the class in the Factory mode new
. For future versions of JavaScript, a suggestion was made to be able to customize new
the behavior of the class constructor when ignoring _. However, this approach still increases the cost of using class (which means fewer people will use it).
2. When invoking the API, the instantiated details are compromised (from
new
Angle expansion)
The calling method of the constructor is tightly coupled to the way the constructor is implemented. Refactoring can be a huge change when you need the flexibility of a factory approach. Refactoring the class into the factory method is very common, and it is even written to Martin Fowler, Kent Beck, John Brant, William Opdyke, and Don Roberts's "refactoring:improving The Design of Existing Code.
3. The constructor mode violates the open/close principle
Due to the new
requirements of _ _, the constructor violates the on/off principle: that an API should be open to the extension, the modification is closed.
My opinion is that since refactoring from class to factory methods is very common, you should not cause any damage as standard when all constructors are expanded.
If you open a constructor or a class and the user uses the constructor, after that, if you need to increase the flexibility of this method (for example, by using an object pool, or by instantiating it across execution contexts, or using alternative prototypes to have more inheritance flexibility), All require the user to refactor at the same time.
Unfortunately, in JavaScript, switching from constructors or classes to factory methods requires a huge change :
//Original implementation://Original implementation://class Car {//Drive () {//Console.log (' vroom! ');// }// }//Const automaker = {Car};//Factory refactored implementation://Factory function Refactoring implementation:ConstAutomaker= { Car(bundle){ return Object.Create( This.Bundle[Bundle]); }, Bundle: { Premium: { Drive(){ Console.Log(' vrooom! '); }, getoptions: function(){ return[' Leather ', ' Wood ', ' Pearl ']; } } }};//The Refactored factory expects://Refactoring method is expected to call thisConstNewcar= automaker.Car(' Premium ');Newcar. Drive(); //' vrooom! '//But since it's a library, lots of callers//In the wild is still doing this://But since this is a library, many users still use thisConstOldcar= New automaker.Car();//Which of course throws://Typeerror:cannot Read property ' undefined ' of//undefined at new Automaker.car//In this case, it will be thrown://Typeerror:cannot Read property ' undefined ' of//undefined at new Automaker.car
In the example above, we first provided a class, but then we wanted to provide different kinds of cars. As a result, the factory method used different prototypes for different car types. I used this technique to store different player interfaces and then choose the right prototype for the file format to be processed.
4. Using constructors can cause
instanceof
is deceptive
Compared with the factory method, the great change of the constructor is instanceof
the performance of _. People sometimes use instanceof
a type check. This approach is often problematic, and I recommend that you avoid using instanceof
_.
> instanceof
will lie.
//instanceof is a prototype identity check.//Not a type check.//instanceof is a prototype check//rather than type checking//That means it lies across execution contexts,//When prototypes is dynamically reassigned,//And when you throw a confusing cases like this//At it:function Foo(){}ConstBar= { a: ' A '};Foo.prototype =Bar;//Is bar an instance of Foo? nope!Console.Log(BarinstanceofFoo; //False//Ok ... since bar isn't an instance of Foo,//Baz should definitely not be a instance of Foo, right?ConstBaz= Object.Create(bar);// ... Wrong.Console.Log(BazinstanceofFoo; //True. Oops.
_ instanceof
type checking is not the same as a strongly typed language, and it checks the objects and properties of the object for [[Prototype]]
Constructor.prototype
consistency.
For example, an error occurs when the execution context changes instanceof
. When Constructor.prototype
it changes, instanceof
_ does not work as expected.
When you start with a class or constructor (which will return to Constructor.prototype
the this
point) and then instead explore another object (without pointing Constructor.prototype
to it), this also causes instanceof to fail. This situation occurs when you convert a constructor to a factory function.
In short, _ instanceof
_ is another big change that happens when you convert a constructor to a factory function.
Advantages of using Class
- Convenient, self-contained syntax.
- is a single, canonical way of using a class in JavaScript. Prior to ES6, the implementation had already occurred in some popular libraries.
- It's more familiar to people who have backgrounds based on class language.
Disadvantages of using Class
In addition to the disadvantages of having constructors, there are:
- The user may try to use the extends keyword to create a class that causes the problem in a multilayer level.
Multi-tier classes will lead to many issues that are well known in object-oriented programming bcc, including fragile base-class problems, banana-Monkey rainforest problems, the need for repetitive problems , and so on. Unfortunately, class can be used to extends like balls can be used to throw, and chairs can be used to sit as naturally. For more information, please read the "Pillars of Javascript:prototypal OO" and "Inside the Dev Team death Spiral".
It is worth noting that both constructors and factory functions can lead to problematic hierarchy inheritance, but with the _ extends
keyword, class provides a functional visibility that makes you err. In other words, it encourages you to think about inflexible and often wrong _is-a_ relationships, rather than more flexible _has-a or _can-do_ component relationships.
> Functional visibility is an opportunity for you to perform certain actions. For example, knobs can be used to rotate, levers can be used to pull, buttons can be used to press, and so on.
Advantages of using the factory method
Factory methods are more flexible than constructors or classes, and it does not entice people to use _ extends
_ to construct too deep inheritance hierarchies. You can use several methods to inherit factory functions. In particular, if you would like to know about the modular factory approach, please see Stamp specification.
1. Returning arbitrary objects and using arbitrary prototypes
For example, you can easily create multiple types of objects from the same API, such as a media player capable of instantiating players for different types of video, and live to be able to set up event libraries for DOM events or Web socket events.
The factory function can also instantiate objects across the row context, take full advantage of the object pool, and allow more flexible prototype model inheritance.
2. No re-construction concerns
You never need to convert from a factory to a constructor, so refactoring will never be a problem.
3. No _
new
_
There new
is only one option to use _, that is, do not use. (This will result this
in a bad performance, for the next point).
4. The standard _
this
_ Behavior
this
It is the same as it usually does, so you can use it to get its parent object. For example, in player.create()
, this
point to Player, just as other method calls do. and _ will also be the same point _. call()
apply()
this
5. There is no deceptive _
instanceof
_ Question 6. Some people like
myFoo = createFoo()
The disadvantage of this method of writing a factory
- Does not create a link to _-
Factory.prototype
But it is a good thing because you do not get a deceptive one instanceof
. Instead, instanceof
_ will always fail. See the advantages of the factory method for details.
- _
this
_ does not point to a new object in the factory method. See the advantages of the factory method for details.
- In a micro-optimized benchmark, the factory method may be slightly slower than the constructor pattern. If this affects you, be sure to test it in the context of your program.
Conclusion
In my opinion, _ class
may have a simple grammatical form, but it does not compensate for the fact that it tempts careless users to err in class succession. It is risky for the future because you might want to upgrade it to a factory function, and because the new
_ keyword, all your calls will be tightly coupled to the constructor, then migrating from class to factory method will be a huge change.
You might think that you can refactor only the invocation part, but in a large team, or you use a class that is part of a public API, you might want to break code that is not in your control. In other words, you cannot assume that only the refactoring call part is always an option.
The interesting thing about factory methods is that they are not only more powerful and flexible, but also the simplest way to encourage the entire team and all API users to use simple, flexible, and secure patterns.
There is much more to be detailed about the benefits of factory functions, especially the ability to combine objects. To learn more, and how this differs from class inheritance, read "3 Different kinds of prototypal inheritance".
For more training in Prototypal inheritance techniques, factory functions, and object composition, is sure to check out "The Pillars of Js:composition with prototypes" is?—? free for members. Not a member yet?
Learn JavaScript with Eric Elliott
Eric Elliott_ is the author of "Programming JavaScript Applications" (O ' Reilly), and "Learn JAVASCRI PT with Eric Elliott ". He has contributed to software experiences for Adobe Systems, Zumba Fitness, the Wall Street Journa L, ESPN, BBC, and top recording artists including Usher, Frank Ocean, Metallica, and many more._
He spends most of its time in the San Francisco Bay area with the most beautiful woman in the world.
The factory method, constructor, and class in JavaScript