Catalog
Why does Javascript not have a method signature?
Parasitic combinatorial inheritance
Prototype Chain
A prototype chain is a relationship between a prototype object and an instance object through the property uProto_uContact.
inherit
Inheritance is a mechanism that allows us to create new classes based on existing classes, which can use all the functions of the parent class and can be extended on top of them.There are two ways to inherit, one is interface inheritance, the inheritance method signature (method name and parameter type composition), the other is to implement inheritance, inherit the actual method, javascript has no method signature and can only support the implementation of inheritance.
Why does Javascript not have a method signature?
First of all, javascript is a loose type or dynamic language. It is not necessary to declare the type of variable beforehand. When the handler is working, the type is determined automatically, and the method signature is composed of the method name and parameter type. Native javascript has no type check, how many parameters are passed, what type of parameters are, and the parser will not verify it.The parameters of javascript are represented by an array of 0 or more values. Unlike other languages, function signatures are created beforehand, and subsequent calls to functions are set as function signatures, so javascript has no method signatures.
function Target(param) { console.log(param) //Output hi, the number of parameters defining a function can be different from the number of parameters passed in from the calling function } Target("hi",'world')
We continue to talk about inheritance.
Inheritance is divided into: prototype chain inheritance, constructor inheritance, combination inheritance, parasitic combination inheritance
Prototype Chain Inheritance
function Target() { this.params = ["a","b","c"] } function Follow() {} Follow.prototype = new Target() let follow_first = new Follow() follow_first.params.push("f") let follow_second = new Follow() follow_second.params.push("g") console.log(follow_first.params) // Output ['a','b','c','f','g'] console.log(follow_second.params) // Output ['a','b','c','f','g']
We use the property prototype of the constructor Follow to point to the instance object created by the constructor Target, and then use the constructor Follow to create two instance objects follow_first, follow_second, since the prototype object can be shared by the instance object created by the constructor, the instance object follow_first, follow_Seconds add elements to their own property params array, which is actually adding elements to the prototype object's property params array, so their property params array outputs the same result.
And then about what I see online:
In javascript's prototype chain inheritance, subclasses cannot pass parameters when calling the parent's constructor.
But I write my own code to try:
function Target(name) { this.params = ["a","b","c"] this.name = name } function Follow() {} Follow.prototype = new Target("Ben") console.log(Follow.prototype)
Output results:
Indicates that parameters can be passed in to the constructor, so I looked for an answer on the web and found a more reasonable answer:
It is not that the syntax cannot transfer the constructor's parameters, but that it does not conform to the rules of object-oriented programming. The object is the owner of the property. If the name property is assigned to the object before calling the constructor Target, the instance object created by the following constructor Follow will have the value of the name property.However, the value of this name attribute may not be what the instance object wants, but is forced to have the value of this attribute.
Benefits of prototype chain inheritance:
Subclasses can find the properties of the parent class by looking up the prototype chain.
Disadvantages of prototype chain inheritance:
Instances created by the constructor share the object that the prototype points to, and manipulating the properties of the object that the prototype points to can cause problems.
Define a method in the instance object to prevent renaming the method as defined by the parent class.
A subclass cannot pass parameters when calling its parent's constructor.
Constructor Inheritance
function Target(name) { this.params = ["a","b","c"] this.name = name this.fun = function () { return this.params } } Target.prototype.fun_extra = function () { console.log("go") } function Follow(name) { Target.call(this,name) } let follow_first = new Follow("Ben") follow_first.params.push("g") console.log(follow_first.params) // Output ['a','b','c','g'] console.log(follow_first.name) // Output Ben console.log(follow_first.fun) // outputƒ () { return this.params } console.log(follow_first.fun()) // Output ['a','b','c','g'] console.log(follow_first.fun_extra) // Output undefined console.log(follow_first.fun_extra()) //Output Uncaught TypeError: follow_first.fun_extra // is not a function let follow_second = new Follow("Ken") follow_second.params.push("f") console.log(follow_second.params) // Output ['a','b','c','f'] console.log(follow_second.name) // Output Ken console.log(follow_second.fun) // outputƒ () { return this.params } console.log(follow_second.fun()) // Output ['a','b','c','f'] console.log(follow_second.fun_extra) // Output undefined console.log(follow_second.fun_extra()) // Output prototype 1.js:33 Uncaught TypeError: // follow_second.fun_extra is not a function
Constructor inheritance solves the problem that subclasses cannot pass parameters when calling the parent class's constructor to work with multiple instance objects to manipulate the properties of the object that the prototype points to. It also causes the problem that the prototype definition method of the parent class is not available to the subclass, and that instances of the subclass can only use the properties bound by the parent class this.
Advantages of constructor inheritance:
Resolved that a subclass cannot pass parameters when calling its parent's constructor
Avoid the problem of multiple instance objects working together on the properties of the object that the prototype points to
Disadvantages of constructor inheritance:
The prototype definition method of the parent class is not available for the child class, and instances of the child class can only use properties bound by the parent class this
Methods defined in constructors cannot be overridden
Combinatorial Inheritance
function Target(name) { this.params = ["a","b","c"] this.name = name } Target.prototype.fun = function () { return this.params } function Follow(name) { Target.call(this,name) } Follow.prototype = new Target() Follow.prototype.constructor = Follow let follow_first = new Follow("Ben") follow_first.params.push("g") console.log(follow_first.params) //Output ['a','b','c','g'] console.log(follow_first.fun()) //Output ['a','b','c','g'] let follow_second = new Follow("Ken") follow_second.params.push("f") console.log(follow_second.params) //Output ['a','b','c','f'] console.log(follow_second.fun()) //Output ['a','b','c','f']
Advantages of combined inheritance:
Solves the problem that instance objects inherited from the prototype chain share the properties of the prototype object, resulting in poor property isolation of the instance object.
Solves the problem that the prototype definition method of the constructor inheriting the parent class is not available to the child class.
Disadvantages of combinatorial inheritance:
The parent's constructor is called twice, once by the callfunction and once by the new keyword, resulting in the prototype and instance objects having the same properties.
Prototype Inheritance
function Target(object) { function Follow() {} Follow.prototype = object return new Follow() }
Prototype inheritance encapsulates prototype chain inheritance without the need to create new constructors and reduce the amount of code.However, there are still drawbacks to prototype chain inheritance.
Parasitic Inheritance
function Target(object) { function Follow() {} Follow.prototype = object return new Follow() } function createTarget(originObject) { let newObject = Target(originObject) newObject.method = function () { console.log("hello") } return newObject }
Parasitic inheritance is also an encapsulation process, which adds properties or methods to newly created instance objects based on prototype inheritance, but these properties and methods are private and cannot be shared.
Parasitic combinatorial inheritance
function create(object) { function A() {} A.prototype = object return new A() } function Target(name) { this.params = ["a","b"] this.name = name } Target.prototype.fun = function () { return this.params } function Follow(name) { Target.call(this,name) } function inheritPrototype(follow,target) { let prototype = create(target.prototype) prototype.constructor = follow follow.prototype = prototype } inheritPrototype(Follow,Target) let follow_first = new Follow("Ben") console.log(follow_first.name) //Output Ben
Diagram:
Parasitic combination inheritance reduces the number of calls to the parent constructor, replaces the instance object created by the parent constructor with an empty object so that the property prototype of the subclass points to the empty object, avoids that the prototype object and the instance object have the same properties, and the instance object created by the subclass can override the method of the parent class.Parasitic combinatorial inheritance has the advantages of prototype chain inheritance and constructor inheritance.
There is also a class inheritance, which I will introduce later.