Factory mode -> constructor mode: solve the problem of object type recognition

Function createPerson(name,age){var o=new Object(); o.name=name; o.age=age; o.sayName=function(){ alert(this.name); } return o; } var p=createPerson("Alice",20); console.log(p); Function Person(name,age){this.name=name; this.age=age; this.sayName=function(){ alert(this.name); } } var p=new Person("Cindy",20); console.log(p);Copy the code

The prototype chains look different from the instance objects they output.

Factory pattern prototype chain: Instance Object ->Object constructor’s prototype Object, p.constructor outputs Object.

Constructor pattern prototype chain: instance Object -> prototype Object of the Person constructor -> prototype Object of the Object constructor, p.constructor outputs Person.

This difference allows the constructor pattern to be used for object recognition, that is, until the object is of what type. You can use constructor and instanceof for type judgment.

console.log(p.constructor==Person)  //true
console.log(p instanceof Person)    //true
Copy the code

Constructor pattern -> Prototype pattern: to solve the problem of code reuse when creating multiple objects

1. Object attribute search mechanism: search along the prototype chain and stop the search when it is found. The object instance itself is searched to see if it has the property. If it does not, the prototype object is searched along the prototype chain (the object to which __proto__ points) until the last prototype object in the prototype chain is found.

2. The relationship between objects, constructors, and prototype objects: one constructor corresponds to one function prototype object, and n objects created by constructors correspond to the same constructor prototype object (i.e. the prototype object of constructors).

Based on the above two points, to achieve n object shared properties or methods, these properties and methods are defined on the prototype object, can accept a lot of memory space. And the prototype is dynamic, modify the attribute values in the prototype, can be reflected in all objects.

However, the disadvantages of using the stereotype pattern alone are obvious. The function definition is fine on the stereotype, but if the reference type is placed on the stereotype, it will cause all objects to share the reference type.

Third, the combination of constructor pattern and prototype pattern: it is the best pattern to deal with the relationship between common and unique

Constructors define properties that are unique to objects, and stereotypes define properties that are common to objects.

function Person(name,age){
	this.name=name;
	this.age=age;
}
Person.prototype.sayName=function(){
	console.log(this.name);
}

var p1=new Person("Cindy",20);
var p2=new Person("Alice",25);
p1.sayName()  //Cindy
p2.sayName()  //Alice
Copy the code

ES6 Class syntax – syntactic sugar for constructor and stereotype patterns

class Person1{
	constructor(name,age){
		this.name=name
		this.age=age
	}
	country="China";
	sayName=function(){
		alert(this.name);
	}
	sayContry(){
		alert(this.country);
	}
}
var p=new Person1("Aclie",22)
Copy the code

The output of object p is:

Person1 {country: "China", name: "Alice", age:20, sayName: ƒ} age:20 Country: "China" name: "Alice" sayName: ƒ () [[Prototype]]: ƒ : Manufacturer () [[Prototype]] ƒ Object ()...Copy the code

The constructor() function is not required, but writing a constructor helps define the object’s unique properties by passing parameters. Properties defined in the constructor are properties of the object instance.

2. An attribute defined by an expression in a class, whether a primitive type (country), a reference type, or a function (sayName), is an attribute of an object instance.

3. Functions defined in class using function declarations are the methods on the constructor prototype.

Dynamic stereotype patterns — Constructor patterns and stereotype patterns are encapsulated in constructors

I think with class syntax sugar, there’s no need for this kind of hard encapsulation.

function Person(name,age){ this.name=name; this.age=age; if(typeof this.sayName! =="function"){ Person.prototype.sayName=function(){ console.log(this.name); }}}Copy the code

Two Special patterns of constructor Pattern extension — Special Purpose (Extension)

(1) Parasitic constructor mode

The constructor does not return a value and is the normal constructor pattern.

The constructor returns a value, which is the parasitic constructor pattern. The function call context assigns to the returned object, that is, this refers to the new object.

function Person(name,age){
	var o=new Object();
	o.name=name;
	o.age=age;
	o.sayName=function(){
		alert(this.name);
	}
	return o;
}
var p=new Person("Alice",20);
console.log(p);
Copy the code

See that the Person function is the same as the factory mode, but is called with the new keyword. In this way, the prototype chain is also the prototype Object of the instance Object ->Object constructor, so it cannot be used to identify the Object type and has no shared advantage. So what is it used for?

JavaScript has many built-in objects, such as arrays, and if you want to add methods to the built-in objects to make them easier to use, you can do so using the parasitic constructor pattern.

function SpecialArray(){ var arr=new Array(); arr.push(... arguments); / / add a special methods arr. ToPipedString = function () {return this. Join (" | "); } return arr; } console.log(colors.toPipedString()); / / output red | blue | green console. The log (colors. Length) / / output 3 colors. Slice (0, 2) / / output [" red ", "blue"]Copy the code

As you can see, Array objects modified using the parasitic constructor mode not only have new methods, but also can use the original Array object properties and methods, which is not very nice.

(2) Safe constructor mode

This pattern is suitable for situations where the this and new keywords are not used. At first glance, the factory mode code looks almost identical, except that the this keyword is not used. Like the parasitic constructor pattern, it cannot be used to identify object types and has few shared advantages, the biggest being security.

function createPerson(name,age){ var o=new Object(); o.name=name; o.age=age; o.sayName=function(){ alert(name); } return o;} return o;} return o;} return o;} return o; } var p=createPerson("Alice",20); console.log(p); P.sayname () // print "Alice"Copy the code