Prototype of JavaScript
Prototype based programming is also a way of object-oriented programming. Like JavaScript is a prototype based programming idea. There is no concept of class in JavaScript. Even the class introduced in ES6 is essentially a syntactic sugar based on prototype inheritance. No new object-oriented inheritance model is introduced.
Prototype concept of Js
In js, every object has a property called proto, which is the prototype. Let's take an example to see what it is.
If we have two objects
var foo = {name: "foo", one: 1, two: 2}; var bar = {three: 3};
Then let's change the bar's "proto" property to point to foo
bar.__proto__ = foo; // foo is now the prototype of bar.
Then we can access the variables in foo if the prototype object of bar is foo
//Here the output is 1 bar.one // Of course, its own properties can also be accessed, and output 3 bar.three //In this example, we find that bar object has a copy of its prototype object, that is to say, modifying the properties in its prototype does not cause the original prototype object to be modified bar.name = "bar"; //Output foo foo.name; //Output bar bar.name;
In JavaScript, there is also a prototype property. It needs to be explained that one is "proto" and the other is prototype
-
__proto__
It is a pointer used by all objects to link prototypes.
-
prototype
It is a property of a Function object in JavaScript. It can be understood that when a new Function object is used, it points to the corresponding prototype object
There are two forms of objects in JavaScript, one is Object and the other is Function
For an Object, the default value of an Object is "proto" = = Object. Prototype
For Function objects, the default Function. Proto = Function.prototype
// Object var a = { x: 10, calculate: function (z) { return this.x + this.y + z; } }; // Function object function Person(){ }
The prototype chain of Object is easy to understand. Let's take an example
var a = { x: 10, calculate: function (z) { return this.x + this.y + z; } }; var b = { y: 20, __proto__: a }; var c = { y: 30, __proto__: a }; // call the inherited method b.calculate(30); // 60 c.calculate(40); // 80
The prototype chain structure of the above example is shown in the figure below
Of course, according to the js specification, we should use the official writing method to use inheritance
var b = Object.create(a, {y: {value: 20}}); var c = Object.create(a, {y: {value: 30}});
Description of official documents
/** * Creates an object that has the specified prototype or that has null prototype. * @param o Object to use as a prototype. May be null. */ create(o: object | null): any; /** * Creates an object that has the specified prototype, and that optionally contains specified properties. * @param o Object to use as a prototype. May be null * @param properties JavaScript object that contains one or more property descriptors. */ create(o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any;
For Function objects, let's look at the following code
// A writing method of constructor function Foo(y) { this.y = y; } // Modify the prototype of Foo and add a member variable x Foo.prototype.x = 10; // Modify the prototype of Foo and add a member function calculate Foo.prototype.calculate = function (z) { return this.x + this.y + z; }; // Now, we use the Foo prototype to create b and c var b = new Foo(20); var c = new Foo(30); // Call the method in the prototype to get the correct value b.calculate(30); // 60 c.calculate(40); // 80
The layout of its prototype chain is shown in the figure below,
First, the Foo function object will have a prototype property, which will be automatically generated by the system. The constructor property of the object will be changed to point to itself by default, that is, the Foo object. The. proto? Of the Foo function object points to Function.prototype. The. proto? Of its Foo.prototype object points to Object.prototype.
The above association can be verified by the following methods
b.__proto__ === Foo.prototype, // true c.__proto__ === Foo.prototype, // true b.constructor === Foo, // true c.constructor === Foo, // true Foo.prototype.constructor === Foo, // true b.calculate === b.__proto__.calculate, // true b.__proto__.calculate === Foo.prototype.calculate // true
After understanding the above knowledge, take a look at the object-oriented play of js.
Defining parent class
//Define human class var Person = function (fullName, email) { this.fullName = fullName; this.email = email; this.speak = function(){ console.log("I speak English!"); }; this.introduction = function(){ console.log("Hi, I am " + this.fullName); }; }
Defining subclasses
//Define Student class var Student = function(fullName, email, school, courses) { //Use call to change this point, and point the method attribute this in the parent class to Student Person.call(this, fullName, email); // Initialize our Student properties this.school = school; this.courses = courses; // override the "introduction" method this.introduction= function(){ console.log("Hi, I am " + this.fullName + ". I am a student of " + this.school + ", I study "+ this.courses +"."); }; // Add a "exams" method this.takeExams = function(){ console.log("This is my exams time!"); }; };
Use prototype chain to inherit and associate objects
// Create a Student.prototype object that inherits // from Person.prototype. Student.prototype = Object.create(Person.prototype); // Set the "constructor" property to refer to Student Student.prototype.constructor = Student;
Verify that we succeeded in inheriting
var student = new Student("Ai Xue xi", "aixuexi@hotmail.com", "XYZ University", "Computer Science"); student.introduction(); student.speak(); student.takeExams(); // Check that instanceof works correctly console.log(student instanceof Person); // true console.log(student instanceof Student); // true
class is introduced into ES6, which is more convenient for us to use inheritance, which is much clearer and more convenient than ES5's implementation of inheritance by modifying the prototype chain.
class A{ constructor(name,age){ this.name = name; this.age = age } } class B extends A{ constructor(name,age,addr){ super(name,age); this.addr = addr } } var a = new A("1",2); var b = new B("!",2,"3"); console.log(b instanceof B) console.log(b instanceof A)