Javascript archetypes, prototype chains, inheritance
Prototype and prototype chain are very important knowledge points in JavaScript. To understand prototype, we should start from JavaScript objects first. This paper will gradually explain prototype and prototype chain in depth.
Create an object
The factory pattern
Factory pattern is a broad design pattern in software engineering. This pattern abstracts the process of creating concrete objects. Developers invent a function that encapsulates the creation of objects
function createPerson(name, age, job) {
var o = new Object(a); o.name = name; o.age = age; o.job = job; o.sayName =function() {
alert(this.name)
}
return o
}
var person1 = createPerson("Nicholas".20."software engineer")
var person2 = createPerson("Greg".21."Doctor")
Copy the code
The factory pattern solved the problem of creating multiple similar objects, but it didn’t solve the problem of object recognition (how to know the type of an object). With the development of JavaScript, a new pattern emerged
Constructor pattern
function Person(name, age, job) {
this.name = name
this.job = job
this.age = age
this.sayName = function() {
alert(this.name)
}
}
var person1 = new Person("Nicholas".20."software engineer")
var person2 = new Person(Greg"21,"Doctor)
Copy the code
In addition to replacing the createPerson() function with the Person() function, we also notice that the code in Person() is the same as that in createPerson().
- There is no explicit creation object
- We assign attributes and methods directly to this
- No return statement
Creating a custom constructor means that its instance can be identified as a specific type in the future, which is where the constructor pattern trumps the engineering pattern.
Constructors, while useful, are not without their drawbacks. The main problem with using constructors is that each method has to be recreated on an instance, and functions of the same name are not equal on different instances, as the following code demonstrates.
alert(person1.sayName == person2.sayName); // false
Copy the code
The prototype pattern
Each function we create has a Prototype property, which is a pointer to an object whose purpose is to contain properties and methods that can be shared by all instances of a particular type. If taken literally, Then the prototype is by calling the constructor and create instances of the object prototype object, use can make all the objects are the benefits of a prototype object instance Shared it contains properties and methods, in other words, don’t have to be defined in the constructor object instance information, but this information can be added directly to the prototype object, such as the following examples
function Person() {
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 20;
person.prototype.job = "software engineer";
Person.prototype.sayName = function() {
alert(this.name)
}
var person1 = new Person()
var person2 = new Person()
alert(person1.name == person2.name) // true
Copy the code
The constructor is used to create a new object with the same properties and methods, but unlike the constructor pattern, these properties and methods are shared by all instances. In other words, person1 and person2 access the same set of properties and the same sayName function. To understand how the stereotype pattern works, you must first understand the nature of the stereotype object in ECMAScript.
Here’s the big part
Understanding prototype objects
Whenever a new function is created, a Prototype property is created for that function according to a specific set of rules. This property points to the function’s Prototype object. By default, all Prototype objects automatically get a constructor property, pointing to the constructor
Problems with prototype objects
Prototype model is not without its drawbacks, first of all, it omitted the initialization parameters for the constructor transfer this link, the results of all instances by default will get the same attribute values, although it will bring some inconvenience to some extent, but not the prototype of the biggest problems, archetypal pattern of the biggest problem is by its nature of sharing.
All attributes in the stereotype are shared by many instances, which is fine for functions. It makes sense that attributes that contain base values can be hidden from the stereotype by adding an attribute of the same name to the instance. However, the problem is more pronounced for attributes that contain reference type values, as shown in the following example.
function Person() {
}
Person.prototype = {
constructor: Person,
name: "Nicholas".age: 20.job: "software engineer".friends: ["Shelby"."Court"].sayName: function() { alert(this.name) }
}
var person1 = new Person()
var person2 = new Person()
person1.friends.push("Van");
alert(person1.friends) // "Shelby, Court Van"
alert(person2.friends) // "Shelby, Court Van"
alert(person1.friends === preson2.friends) // true
Copy the code
The Person.prototype object has a property called frends, which is an array, creates two instances, and then modifies the array referenced by person1.friends by adding a string to the array. Since friends is in Person.prototype and not person1, this change will also be reflected by person2.friends. If our original intention was for all instances to share an array, there is nothing to be said for this result. However, instances generally have all their own attributes, which is why archetypal patterns are rarely used in isolation.
Use a combination of constructor and stereotype patterns
The most commonly used way, create a custom type is combined constructor mode in the prototype, the constructor mode is used to define instance attributes, and the prototype model used to define the method and the Shared attribute, as a result, each instance will have their own a copy of the instance attributes, but at the same time and share with the reference of the method, maximum limit save the memory, in addition, This hybrid pattern also supports passing parameters to constructors, which is the length of the two patterns. Let’s start with the previous example.
function Person(name, age, job) {
this.name = name
this.age = age
this.job = job
this.friends = ["Shelby"."Court"]
}
Person.prototype = {
constructor: Person,
sayName: function() {
alert(this.name)
}
}
var person1 = new Person("Nicholas".20."software engineer")
var person2 = new Person("Greg".21."Doctor");
person1.friends.push("Van")
alert(person1.friends) // "Shelby, Court, Van"
alert(person2.friends) // "Shelby, Court"
alert(person1.friends === person2.friends) // false
alert(person1.sayName === person2.sayName) // true
Copy the code
In this example, the instance attributes are defined in the constructor, while the constructor and method sayName shared by all instances are defined in the stereotype, and modifying person1.friends does not affect person2.friends because they refer to different arrays.
The first part analyzes and solves problems step by step by creating objects, leading to the concept of prototype. The second part will lead to the prototype chain by inheritance
inheritance
Inheritance is implemented in ECMAScript primarily through prototype chains
Prototype chain
The stereotype chain concept: each constructor has a stereotype object, each stereotype object contains a pointer to the constructor, and each instance contains an internal pointer to the stereotype object. What if we made the stereotype object equal to an instance of another type? Obviously, as the prototype of the object will contain a pointer to another prototype, response to, another prototype also contains a pointer to another constructor, if another prototype are another type of instance, then established the relationship still, so walk, constitutes instance and the prototype chain, this is known as the basic concepts of the prototype chain.
Combination of inheritance
Combination of inheritance is also called the classical inheritance, refers to the prototype chain and borrow technology portfolio to a constructor, so as to exert the long an inheritance model, the idea behind it is using the prototype chain implementation of prototype properties and methods of inheritance, and by borrowing the constructor to implement for instance attribute inheritance, in this way, by definition on prototype method not only realize the function of reuse, It also ensures that each instance has its own attributes.
function SuperType(name) {
this.name = name
this.colors = ["red"."blue"."green"]
}
SuperType.prototype.sayName = function() {
alert(this.name)
}
function SubType(name, age) {
SuperType.call(this, name)
this.age = age
}
SubType.prototype = new SuperType()
SubType.prototype.constructor = SubType
SubType.prototype.sayAge = function() {
alert(this.age)
}
var instance1 = new SuperType("Nicholas".20)
instance1.colors.push("black")
alert(instance1.colors) // "red", "blue", "green", "black"
instance1.sayName() // "Nicholas"
instance1.sayAge() / / 20
var instance2 = new SuperType("Greg".21)
alert(instance2.colors) // "red", "blue", "green"
instance2.sayName() // "Greg"
instance2.sayAge() / / 21
Copy the code