Constructor Pattern in JavaScript Design Patterns

introduce

Constructors are familiar to everyone, but if you are a novice, it is necessary to understand what a constructor is. Constructors are used to create objects of a specific type - not only do they declare the objects to be used, but they can also accept parameters to set the member values ​​of the object when it is first created. You can customize your own constructor, and then declare properties or methods of custom type objects in it.

Basic usage

In JavaScript, constructors are usually considered to be used to implement instances. JavaScript has no concept of classes, but has special constructors. By calling the defined function with the new keyword, you can tell JavaScript that you want to create a new object and that the member declarations of the new object are defined in the constructor. Inside the constructor, the this keyword refers to the newly created object. The basic usage is as follows:

function Car(model, year, miles) {    this.model = model;    this.year = year;    this.miles = miles;    this.output= function () {        return this.model + "gone" + this.miles + "kilometer";    };}
var tom= new Car("uncle", 2009, 20000);var dudu= new Car("Dudu", 2010, 5000);
console.log(tom.output());console.log(dudu.output());

The above example is a very simple constructor pattern, but it has a little problem. First of all, it is very troublesome to use inheritance, and secondly, output() is redefined every time an object is created. The best way is to let all instances of Car type share this output() method, so that if there are a large number of instances If so, it will save a lot of memory. To solve this problem, we can use the following methods:

function Car(model, year, miles) {    this.model = model;    this.year = year;    this.miles = miles;    this.output= formatCar;}
function formatCar() { return this.model + "gone" + this.miles + "kilometer";}

Although this method is available, we have a better method as follows.

Constructor and Prototype

In JavaScript, functions have a prototype property called prototype. When a constructor is called to create an object, all the properties of the constructor prototype are available on the newly created object. In this way, multiple Car object instances can share the same prototype. Let's expand the code of the above example:

function Car(model, year, miles) {    this.model = model;    this.year = year;    this.miles = miles;}
/*Note: Here we use the Object.prototype. method name instead of Object.prototype is mainly used to avoid overriding the definition of the prototype prototype object*/Car.prototype.output= function () { return this.model + "gone" + this.miles + "kilometer";};
var tom = new Car("uncle", 2009, 20000);var dudu = new Car("Dudu", 2010, 5000);
console.log(tom.output());console.log(dudu.output());

Here, the single instance of output() can be shared among all Car object instances. Also: We recommend starting constructors with a capital letter to distinguish them from ordinary functions.

Can only use new?

The above example uses new to create objects for the function car. Is there only one way? In fact, there are other ways, we list two:

function Car(model, year, miles) {    this.model = model;    this.year = year;    this.miles = miles;    // Customize an output output content this.output = function () { return this.model + "go" + this.miles + "km"; }}
//Method 1: Call Car("Uncle", 2009, 20000) as a function; //Add to the window object console.log(window.output());
//Method 2: Call var o = new Object() within the scope of another object; Car.call(o, "Dudu", 2010, 5000);console.log(o.output());

Method 1 of this code is a bit special. If you don't use new to directly call the function, this points to the global object window. Let's verify it:

//As a function call var tom = Car("Uncle", 2009, 20000);console.log(typeof tom); // "undefined"console.log(window.output()); // "Uncle walked 20000 kilometers"

At this time, the object tom is undefined, and window.output() will output the result correctly, but if the new keyword is used, there is no such problem. The verification is as follows:

//Use the new keyword var tom = new Car("Uncle", 2009, 20000);console.log(typeof tom); // "object"console.log(tom.output()); // "Uncle left 20000 kilometer"

Force the use of new

The above example shows the problem of not using new, so is there a way for us to force the constructor to use the new keyword? The answer is yes, the code above:

function Car(model, year, miles) {    if (!(this instanceof Car)) {        return new Car(model, year, miles);    }    this.model = model;    this.year = year;    this.miles = miles;    this.output = function () {        return this.model + "gone" + this.miles + "kilometer";    }}
var tom = new Car("uncle", 2009, 20000);var dudu = Car("Dudu", 2010, 5000);
console.log(typeof tom); // "object"console.log(tom.output()); // "Uncle walked 20,000 kilometers"console.log(typeof dudu); // "object"console.log(dudu.output()); // " Dudu walked 5000 kilometers"

Determine whether to return new Car or continue to execute the code by judging whether the instanceof of this is Car. If the new keyword is used, (this instanceof Car) is true, and the following parameter assignments will continue to be executed. If new is not used, (this instanceof Car) instanceof Car) is false, and a new instance will be returned.

original wrapper function

There are 3 primitive wrapper functions in JavaScript: number, string, boolean, and sometimes both are used:

// Using the original wrapper function var s = new String("my string");var n = new Number(101);var b = new Boolean(true);

// This is recommended var s = "my string";var n = 101;var b = true;

It is recommended to use these wrapper functions only when you want to preserve the numerical state. For the difference, you can refer to the following code:

// Primitive stringvar greet = "Hello there";// Use split() method to split greet.split(' ')[0]; // "Hello"// Add new property to primitive type without error greet.smile = true; // There is no way to get this value (we talked about why in Chapter 18 ECMAScript Implementation) console.log(typeof greet.smile); // "undefined"
// Original stringvar greet = new String("Hello there");// Use split() method to split greet.split(' ')[0]; // "Hello"// Add new property to wrapper function type without error greet .smile = true;// The new property can be accessed normally console.log(typeof greet.smile); // "boolean"

Posted by goldages05 on Fri, 13 May 2022 20:46:02 +0300