Although development today uses ES6 classes and TypeScript interface definitions, decorators, etc., it’s important to understand object creation and inheritance prior to ES6 (ES6 classes encapsulate the syntax sugar of constructor + stereotype inheritance).
Creating complex objects
The factory pattern
Used to abstract the process of creating a particular object
function createPerson(name, age, job) {
let o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function () {
console.log(this.name);
};
return o;
}
let person1 = createPerson('echo', 12, 'engineer');
let person2 = createPerson('Jon', 1, 'Doctor');
Copy the code
Problems with the factory model
While this pattern solves the problem of creating multiple similar objects, it does not solve the problem of object identification (what type the newly created object is)
Instead, use constructors to identify instances
Constructor pattern
Constructors in ECMAScript are functions that create (specific type) objects.
Constructors & functions
Constructors are functions, and the only difference is how they are called. Any function called with the new operator is a constructor, otherwise it is a normal function
By management, constructor names are capitalized (borrowed from object-oriented programming languages).
Custom constructors
Native constructors, such as Object and Array, can be used directly by the runtime in the execution environment
You can also customize constructors that define properties and methods for your own object types in the form of functions, ensuring that instances are identified as specific types
function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = function() { console.log(this.name); } } let person1 = new Person('echo', 12, 'engineer'); let person2 = new Person('Jon', 1, 'Doctor'); person1.sayName(); // 'echo' console.log(person1.constructor == Person); // true // constructor is originally used to identify the type of the object, but it is generally considered a more reliable way to determine the type of the object when using the instanceof operator // since the constructor point may be changed console.log(person1) instanceof Person); // true // every Object is an instanceof Object, since all custom objects inherit from Object console.log(person1 instanceof Object); // trueCopy the code
Let person = new person; let person = new person;
The code inside Person() differs from that inside createPerson() as follows:
- Create objects without showing them
- Properties and methods are directly assigned to
this
- There is no
return
Person
Capitalized the first letter of the
To create instances using constructors, use the new operator. Calling the constructor in this way does the following:
Create a new object in memory
2. The [[Prototype]] property inside this new object is assigned to the constructor’s Prototype property.
3. This inside the constructor is assigned to the new object.
4. Execute the code inside the constructor
5. If the constructor returns a non-empty object, it returns that object. Otherwise, the newly created object is returned
Calling a function without explicitly setting itthis
Value (that is, no method is called as an object, or is not usedcall()
/appy()
Call),this
Always point toGlobal
Object (in the browserwindow
Object)
Person('g', 20, 'Doctor'); // Add to the window object window.sayname (); // 'g' let o = new Person(); Person.call(0, 'k', '10', 'Nurse'); o.sayName(); // 'k'Copy the code
Constructor problem
The main problem is that the methods defined are created on each instance, so functions with the same name on different instances are not equal but do the same thing.
Resolve (move function definition outside constructor) :
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = sayName;
}
function sayName() {
console.log(this.name);
}
Copy the code
The above approach solves the problem of repeating functions with the same logic, but it also affects the global scope
So here’s the prototype
The prototype pattern
Each function creates a Prototype property, which is an object containing properties and methods that should be shared by instances of a particular reference type
The advantage of using a stereotype object is that properties and methods defined on it can be shared by the object instance
Values that are assigned directly to object instances in constructors can be assigned directly to their prototypes
function Person() {}
Person.prototype.name = 'echo';
Person.prototype.sayName = function() {
console.log(this.name);
}
const person1 = new Person();
const person2 = new Person();
console.log(person1.sayName == person2.sayName); // true
Copy the code
The above code adds the properties and methods directly to the Person prototype property. The same properties and methods are accessed from instance to instance.
Understand the prototype & prototype chain
Problems with prototype patterns
First, it weakens the ability to pass initialization parameters to constructors, resulting in all instances taking the same property values by default
The main problem stems from its shared nature — properties that contain reference values, and changing this reference value property on one instance causes corresponding properties on other instances to change as well. But in general, different instances should have their own copies of properties. This is why prototyping patterns are usually not used in isolation in real development
function Person() {}
Person.prototype = {
constructor:Person,
name: 'echo',
age: 12,
friends: ['Jon', 'May'],
sayName() {
console.log(this.name);
}
}
let person1 = new Person();
let person2 = new Person();
person1.friends.push('Van');
console.log(person1.friends); // ['Jon', 'May', 'Van']
console.log(person2.friends); // ['Jon', 'May', 'Van']
Copy the code