Built-in constructors and inheritance
Let’s start with two pictures
Two unrelated classes
Think about the relationship between the People class and the Student class
The Student class has all the attributes and methods that the People class has, and extends some of the attributes and methods
Student is a kind of People. **is a kind of person
This is the inheritance relationship: Student inherits from People
inheritance
Inheritance describes the “is a kind of” relationship between two classes
For example, students are a kind of “people”, so there is an inheritance relationship between human beings and students
People is ** “superclass” (or “superclass”, “base class”); Student is a “subclass” **(or “derived class”)
Subclasses enrich the parent class, making the class description more specific and detailed
More examples of inheritance relationships
1. Inheritance through the prototype chain
The key to inheritance is that subclasses must have all the attributes and methods of their parent class, and they should also be able to define their own unique attributes and methods
Make the prototype of the subclass constructor point to an instance of the parent class
It is common practice to implement inheritance using JavaScript’s unique prototype chain feature
// Parent human
function People(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
// this.arr = [33, 44, 55];
}
People.prototype.sayHello = function () {
console.log(I was `The ${this.name}This year,The ${this.age}La `);
};
People.prototype.sleep = function () {
console.log(this.name + "Go to sleep ZZZZ.");
};
// Subclass student class
function Student(name, age, sex, scholl, studentNumber) {
this.name = name;
this.age = age;
this.sex = sex;
this.scholl = scholl;
this.studentNumber = studentNumber;
}
// The core statement implements inheritance
Student.prototype = new People();
Student.prototype.study = function(){
console.log(this.name + "Learning");
}
Student.prototype.exam = function(){
console.log(this.name + "Taking exams, Ollie!");
}
// Subclasses can override the parent sayHello method
Student.prototype.sayHello = function(){
console.log( ` salute! How do you doThe ${this.name}.The ${this.sex}, I come fromThe ${this.scholl}, IThe ${this.age}The `);
}
/ / instantiate
let hanmeimei = new Student("Han Meimei" , 12."Female"."Central Primary School" , 12110);
hanmeimei.study();
hanmeimei.exam();
hanmeimei.sayHello();
hanmeimei.sleep();
let yunmu = new People("YunMu".18."Male");
yunmu.sayHello();
Copy the code
The result is as follows
The problem of inheritance through a chain of prototypes
- Problem 1: If a parent class has a reference type value in an attribute, the attribute is shared by all instances of the child class.
- Problem 2: Subclass constructors often need to repeat many superclass-defined attributes. That is, the constructor of the subclass is not written elegantly;
2. Borrow constructors
- To address the problems of including reference type values in stereotypes and the inelegance of subclass constructors, developers often use a technique called “by virtue of constructors,” also known as “fake objects” or “classical inheritance.”
- The idea of borrowing constructors is simple: call the superclass constructor inside the subclass constructor, but be careful to use the call() binding context
We will modify the above example slightly
// Parent human
function People(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
this.arr = [33.44.55];
}
// Subclass student class
function Student(name, age, sex, scholl, studentNumber) {
// Subclasses use call to bind the parent constructor to this and pass the value
People.call(this, name, age, sex);
this.scholl = scholl;
this.studentNumber = studentNumber;
}
const xiaoming = new Student("Xiao Ming"."Male".12."Central School".100666);
console.log(xiaoming);
xiaoming.arr.push(77);
console.log(xiaoming.arr); // [33, 44, 55, 77]
console.log(xiaoming.hasOwnProperty("arr")); // true
const xiaohong = new Student("Little red"."Female".11."Central School".100667);
console.log(xiaohong.arr); / / [55] 33, 44,
console.log(xiaohong.hasOwnProperty("arr")); // true
Copy the code
3. Combinatorial inheritance
Is the combination of prototype chain inheritance and constructor inheritance, inherit two advantages, also do pseudo-classical inheritance
Inheriting the attributes of the parent class and preserving the advantages of passing arguments by calling the parent constructor,
Then the functions can be reused by using the parent class instance as the prototype of the subclass
Composite inheritance is the most common inheritance pattern in]avaScript
// Subclass student class
function Student(name, age, sex, scholl, studentNumber) {
// Subclasses use call to bind the parent constructor to this and pass the value
People.call(this, name, age, sex);
this.scholl = scholl;
this.studentNumber = studentNumber;
}
// The core statement implements inheritance
Student.prototype = new People();
Copy the code
Disadvantages of combinatorial inheritance
- The biggest problem with combinatorial inheritance is that in any case, you call the superclass constructor twice, right
- Once when the subclass prototype is created, and once inside the subclass constructor
4. Original type inheritance
IE9+ began to support the 0bject.create() method, which allows you to create a new object for your prototype based on a specified object
const obj2 = Object.create(obj1);
Copy the code
const obj1 = {
a: 1.b: 2.c: 3.test() {
console.log(this.a + this.b); }};const obj2 = Object.create(obj1, {
// Add new attributes to obj2
d: {
value: 99
},
// Access overshadows the a attribute on the prototype
a: {
value: Awesome!}});console.log(obj2.__proto__ === obj1); // true
console.log(obj2.a); / / 666
console.log(obj2.b); / / 2
console.log(obj2.c); / / 3
console.log(obj2.d); / / 99
obj2.test(); / / 668
Copy the code
If you want your new Object to be “similar” to an existing Object, use object.create () instead of creating a constructor
Object. Create () is compatible
- How do YOU implement 0bject.create() in older browsers?
// The function creates a new object based on obj
function object(obj) {
// Create a temporary constructor
function F() {}
// Make the temporary constructor's prototype point to O, so that its new object, __proto__, points to O
F.prototype = obj;
// Return an instance of F
return new F();
}
Copy the code
Parasitic inheritance
- Write a function that takes an argument O, returns a new object p modeled after o, and adds a preset new method to p
const o1 = {
name: "Xiao Ming".age: 12.sex: "Male"};const o2 = {
name: "Little red".age: 11,d
sex: "Female"};// Parasitic inheritance
function f(o) {
// Create a new object based on o
const p = Object.create(o);
// Add two methods
p.sayHello = function () {
console.log("Hello, I am." + this.name + "This year" + this.age + "Old");
};
p.sleep = function () {
console.log(this.name + "Sleeping");
};
return p;
}
// get p1 object from o1
const p1 = f(o1);
p1.sayHello(); // Hello, I am Xiao Ming and I am 12 years old
// Get p2 object from o2 object
const p2 = f(o2);
p2.sayHello(); // Hello, I am Xiao Hong and I am 11 years old
Copy the code
-
Parasitic inheritance is simply writing a function that enhances the object
-
Whenever you pass an object into this function, the function creates a new object from that object and assigns new preset methods to the new object
-
Parasitic inheritance is also a useful pattern in cases where objects are primarily considered rather than custom types and constructors
Disadvantages of parasitic inheritance
- Using parasitic inheritance to add functions to objects is inefficient because functions cannot be reused, i.e. “methods are not written to Prototype.”
console.log(p1.sayHello == p2.sayHello); // false
Copy the code
Parasitic combinatorial inheritance
- Parasitic combinatorial inheritance: inherits properties by borrowing constructors and inherits methods through a mashup of stereotype chains
- The basic idea behind this is that instead of calling the constructor of a supertype to specify the stereotype of a subtype,
- ** All we need is a copy of the supertype prototype.
- Essentially, you use parasitic inheritance to inherit the stereotype of the supertype and then assign the result to the stereotype of the subtype.
function People(name) {
this.name = name;
}
People.prototype.eat = function () {
console.log(this.name + " is eating");
};
function Stundent(name, age) {
People.call(this, name);
this.age = age;
}
Stundent.prototype = Object.create(People.prototype);
// The prototype object has a constructor attribute, which by default points to the prototype object's constructor.
Stundent.prototype.contructor = Stundent;
Stundent.prototype.study = function () {
console.log(this.name + " is studying");
};
/ / test
let xiaoming = new Stundent("xiaoming".16);
console.log(xiaoming.name); // xiaoming
xiaoming.eat(); // xiaoming is eating
xiaoming.study(); // xiaoming is studying
Copy the code
The illustration is as follows:
7.ES6 class inheritance
- The class keyword was introduced in ES6, and classes can be inherited using the extends keyword
- You can also define static methods of a class using the static keyword
- This is much cleaner and more convenient than ES5’s inheritance by modifying the prototype chain
- Note that the class keyword is just syntactic sugar for the stereotype, and JavaScript inheritance is still implemented based on the stereotype.
class Person {
// Class constructor
constructor(name, age) {
this.name = name;
this.age = age;
}
// Define the method
showName() {
console.log("Call method of parent class");
console.log(this.name, this.age); }}const p1 = new Person("kobe".39);
console.log(p1);
// Define a subclass
class Student extends Person {
constructor(name, age, salary) {
super(name, age); // Call the parent constructor with super
this.salary = salary;
}
showName() {
// Define methods in the subclass itself
console.log("Calling a subclass's method");
console.log(this.name, this.age, this.salary); }}const s1 = new Student("yunmu".18.1000000);
console.log(s1);
s1.showName(); // yunmu 18 1000000
Copy the code
The instance operator.
- The instanceof operator is used to check whether an object is an instanceof a class, as in:
function People() {}
function Student() {}
Student.prototype = Object.create(People.prototype);
const xiaoming = new Student();
/ / instanceof test
console.log(xiaoming instanceof Student); // true
console.log(xiaoming instanceof People); // true
Copy the code
Again, Ming can find the Student and People prototype properties along the prototype chain, so instanceof is true
Built-in constructor
- JavaScript has many built-in constructors, such as Array (Array), Function (Function), and object (object)
- Built-in constructors are very useful. All methods of this type are defined on the prototype of its built-in constructor. We can extend the functionality of a type by adding new methods to this object
// The built-in constructor for arrays. Any Array literal can be treated as an instance of Array
console.log([1.2] instanceof Array); // true
console.log([] instanceof Array); // true
// Creates an empty array of length 5
const arr = new Array(5);
console.log(arr); //[ <5 empty items> ]
console.log(arr.length); / / 5
// The built-in constructor of a Function. Any Function literal can be treated as an instance of Function
function fun() {}
function add(a, b) {
return a + b;
}
console.log(fun instanceof Function); // true
console.log(add instanceof Function); // true
const decrement = new Function("a"."b"."return a - b");
console.log(decrement(8.3)); / / 5
// The built-in constructor for the object
console.log({ a: 1 } instanceof Object); // true
console.log({} instanceof Object); // true
const o = new Object(a); o.a =2;
o.b = 6;
console.log(o); // { a: 2, b: 6 }
Copy the code
Extension methods
// Methods like push POP are actually methods on array constructor prototypes
console.log(Array.prototype.hasOwnProperty("push")); // true
console.log(Array.prototype.hasOwnProperty("pop")); // true
console.log(Array.prototype.hasOwnProperty("splice")); // true
// Extend the qiuHE method
Array.prototype.total = function () {
/ / accumulator
let sum = 0;
// This represents the array that calls the total() method
for (let i = 0; i < this.length; i++) {
sum += this[i];
}
// Return the result
return sum;
};
const arr1 = [1.2.3.4.5];
const result1 = arr1.total();
console.log(result1); / / 15
const arr2 = [2.8];
const result2 = arr2.total();
console.log(result2); / / 10
Copy the code
“Wrapper classes” for base type values
- Number, String, and Boolean are wrapper classes for the three primitive type values that can be called with new to generate the “object” version of the primitive type values
const o = new Number(3);
console.log(o);
console.log(typeof o); // object
console.log(5 + o); / / 8
const s = new String("abc");
console.log(s);
console.log(typeof s); // object
console.log(String.prototype.hasOwnProperty("slice")); // true
console.log(String.prototype.hasOwnProperty("substring")); // true
console.log(String.prototype.hasOwnProperty("substr")); // true
const b = new Boolean(true);
console.log(b);
console.log(typeof b); // object
Copy the code
Built-in constructor relationships
- Prototype is the end of the prototype chain of everything. In JavaScript, functions and arrays are all objects. Taking arrays as an example, the full prototype chain looks like this:
Testing:
console.log([1.2].__proto__ === Array.prototype); // true
console.log([1.2].__proto__.__proto__ === Object.prototype); // true
console.log([] instanceof Object); // true
console.log([] instanceof Array); // true
console.log(Object.prototype.__proto__); // null null has no __proto__
Copy the code
- Any Function can be regarded as a Function “new”, so let’s have an imagination:
- Function “Object” is a new Function. The answer is yes
- Function is also a Function that can be viewed as an instance of itself
Testing:
console.log(Object.__proto__ === Function.prototype); // true
console.log(Function.__proto__ === Function.prototype); // true
console.log(Object.__proto__.__proto__ === Object.prototype); // true
console.log(Function instanceof Object); // true
console.log(Object instanceof Function); // true
console.log(Function instanceof Function); // true
console.log(Object instanceof Object); // true
Copy the code
If you think this article is good, give it a thumbs up.