JavaScript design is a simple object-based paradigm. An object is a collection of properties, each containing a name and a value. The value of a property can be a function, in which case the property is also called a method

Everything is an object, and an object is a collection of properties and methods that describe the characteristics, functions or effects of a certain class or a single thing.

ES5 Creates an object

Direct object literals

const obj = {
  name: 'dz'.age: 23
}
Copy the code

This method is rigid and not flexible. It needs to be manually created each time and has great redundancy. It is suitable for temporary object variables or objects with few local attributes

Use built-in constructors

const obj = new Object()
obj.name = name
obj.age = age
Copy the code

Only one object can be created, and the reuse is poor. It is easy to create multiple objects with the same content, resulting in code redundancy

The factory pattern

function Person(name, age) {
  const obj = {}
  obj.name = name
  obj.age = age
  return obj
}

const person = Person('dz'.23)
const person1 = Person('dz1'.24)
console.log(person instanceof Person) // -> false
console.log(person1.__proto__ == person.__proto_) // -> false
Copy the code

The object is unrecognizable (which factory function created it), and instances produced by the same factory have different prototypes

function Person(name, age) {
  this.name = name
  this.age  = age
  this.sayname = (a)= > {
    console.log(this.name)
  }
}

const p1 = new Person('dz'.23)
const p2 = new Person('dz1'.24)
console.log(p1 instanceof Person, p2 instanceof Person)// --> true true
Copy the code

Constructors simplify the operation of the factory pattern, and by instantiating an object, you can know its identity, identify which constructor created it, and use instanceof to determine if it belongs to an instanceof a constructor

However, there are methods inside the constructor, which are objects, which means that the method is recreated every time an object (instance) is created, and the repeated creation of the method opens up new memory for storage

The main problem with using constructors is that each method has to be recreated on each instance. Each method acts like a method, and you don’t have to create Function instances repeatedly. And with this, you don’t have to bind the function to a specific object before executing the code.

(js elevation) can be defined outside the constructor to solve the problem. This eliminates the problem of doing the same thing over and over again, but making a method in a global scope called only by a specific object makes the global scope a bit of a dud.

The prototype pattern

function Person(name, age) {
  Person.prototype.name = name
  Person.prototype.age  = age
  Person.prototype.likes  = ['apple'.'banana'.'watermelon']
  Person.prototype.sayname = (a)= > {
    console.log(this.name)
  }
}
const p1 = new Person('dz'.23)
const p2 = new Person('dz1'.24)

p1.likes.pop() Remove remove remove spring
console.log(p1.name == p2.name) // -> true, p2 overwrites p1
console.log(p1.likes) // -> ['apple', 'banana']
console.log(p2.likes) // -> ['apple', 'banana']
Copy the code

Adding properties and methods to the constructor prototype after creating an object has the advantage that each instance shares the same method, avoiding creating the same method over and over again, but the big problem is that everyone shares, so each instance can change the properties in the prototype. The object created later contains properties that override the properties of the object created last time

Instead of defining the information of an object instance in a constructor, you can add this information directly to the prototype object. It can be that the general instance needs all of its own attributes, with few people but using the prototype pattern alone

Composite pattern (constructor pattern + stereotype pattern)

function Person(name, age) {
  this.name = name
  this.age  = age
}

Person.protoytype.sayname = (a)= > {
  console.log(this.name)
}

const p1 = new Person('dz'.23)
const p2 = new Person('dz1'.24)
console.log(p1.name, p2.name)// dz dz1
Copy the code

This approach combines the best of the two, with each instance having its own properties and methods, and sharing the same methods, using more of the same pattern

Dynamic prototype pattern

function Person(name, age) {
  this.name = name
  this.age  = age
  if(typeof this.sayname ! ='function') {
    Person.prototype.sayname = (a)= > {
      console.log(this.name)
    }
  }
}
const p1 = new Person('dz'.23)
console.log(p1.sayname) // -> dz
Copy the code

This is added to the prototype only if the SayName method does not exist and is executed only when the constructor is first called.

Such code makes the name, age, and sex of each object separate (not shared), and then functions written on the prototype are shared again.

Note: When using the dynamic prototype pattern, you cannot rewrite the prototype using object literals. Rewriting a stereotype when an instance has already been created severs the link between the existing instance and the new stereotype.

Here’s an example:

function WPerson(name, age, sex) {
  this.name = name;
  this.age = age;
  this.sex = sex;
  if (typeof this.sayName ! ="function") {
    WPerson.prototype = {   // Here is a prototype rewrite
      constructor: WPerson,
      sayName: function () {
        console.log(this.name); }}}}var per1 = new WPerson("q".18."man");
var per2 = new WPerson("q".18."man");
per1.sayName();  SayName = sayName ()
per2.sayName();  / / output q
console.log(per1.name);  / / output q
Copy the code

To clarify what happens when a new instance is created:

  1. throughnewInstantiate an object, creating a new empty object inside the constructor
  2. Assign the scope of the constructor to the new object. This refers to the new object, that is, inherits the prototype of the function__proto__attribute
  3. Execute the code to add properties and methods to the object via this
  4. Implicit returnreturnThis object

The object has a __proto__ attribute, but the prototype has not been overwritten. For example, per2 has overridden the sayname method before the object has a __proto__ attribute

function WPerson(name, age, sex) {
  this.name = name;
  this.age = age;
  this.sex = sex;
  console.log(this.__proto__) Constructor: ƒ}
  if (typeof this.sayName ! ="function") {
    WPerson.prototype = {   // Here is a prototype rewrite
      constructor: WPerson,
      sayName: function () {
        console.log(this.name); }}}console.log(WPerson.prototype) {constructor: ƒ, sayName: ƒ}
}
var per1 = new WPerson("q".18."man");
var per2 = new WPerson("q".18."man");
per1.sayName();  SayName = sayName ()
per2.sayName();  / / output q
Copy the code

Parasitic constructor

The basic idea is to create a function that simply encapsulates the code that created the object and then returns the newly created object. On the surface, however, this function looks like a typical constructor.

function SpecialArray(){
  var array = new Array(a); array.push.apply(array,arguments);
  array.toPipedString = function(){
      return this.join("|");
  };
  return array;
}
var colors = new SpecialArray("red"."green"."pink");
alert(colors.toPipedString());// red|green|pink
alert(colors instanceof SpecialArray); // false 
Copy the code

We know that when we create an object using a new constructor, we return a new object instance by default. There is no return statement in the constructor. The basic idea of a parasitic constructor is to create a function that simply adds some code for a particular function and then returns the object.

This pattern is no different from the factory pattern, except that it uses the new operator and calls the wrapped functions constructors.

In addition, the object that this SpecialArray() returns has nothing to do with the SpecialArray() constructor or with the constructor’s prototype object, just like any other object that you create outside of SpecialArray(), So if you use the instanceof operator, the result is false. So that’s the problem with it

Secure constructor pattern

For instance, someone else defines a secure object that has no public attributes and whose methods do not refer to this. This pattern is suitable for some secure environments (this and new are prohibited) or to prevent data from being modified by other applications, like the following:

function Person(name,age,gender){
  var obj = new Object(a); obj.sayName =function(){
      alert(name);
  };
  return obj;
}
var person = Person("Stan".0000."male"); // The new operator is not used here
person.sayName(); // Stan
alert(person instanceof Person); // false
Copy the code

Here a secure object is stored in Person, and there is no way to access its data members other than by calling the sayName() method. Even if other code adds methods or attributes to the object, there is no other way to access the raw data passed into the constructor. Similarly to the parasitic function pattern, objects created using the safe constructor pattern have no relationship to the constructor.

ES6 Creates objects

class

class Person {
  constructor(name, age) { // constructor
    this.name = name
    this.age  = age
  }

  sayname() { // On the prototype
    console.log(this.name)
  }
  static sayAge() {
    console.log(this.age)
  }
}

const per = new Person('dz'.23)
per.sayname() // -> dz
Person.sayAge() / / 23
Copy the code

Constructor (sayName, sayname, sayname); sayname (sayname, sayname); sayname (sayname, sayname);

Static: the prototype function does not mount static to the prototype class.

Promise.resolve(...)
Math.max(...)
Copy the code