JavaScript - Inheritance

JavaScript - Inheritance

1. Concept

Inheritance is a core concept in object orientation. Other orthodox object-oriented languages ​​implement inheritance in two ways: one is interface implementation, and the other is inheritance. And ECMAScript only supports inheritance, does not support interface implementation, and the way to implement inheritance relies on the prototype chain to complete.

2. Prototype chain inheritance

[1] Basic concepts:

1. Supertype: The inherited function is called a supertype (also called a parent class or base class).
2. Subtypes: Inherited functions are called subtypes (also known as subclasses, derived classes).
3. Through prototype chain inheritance, the instantiated object instance of the supertype is assigned to the prototype property of the subtype. The prototype of the subtype gets the supertype's construction + the information in the prototype

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>原型链继承</title>
</head>
<body>
    <script>
        function Student(){                 //被继承的函数叫做超类型(父类、基类)
            this.name = 'pangtong';
        }
        function Score(){                   //继承的函数叫做子类型(子类、派生类)
            this.result = 100;
        }

        Score.prototype = new Student();
        var score = new Score();   
        alert(score.result);   //100
        alert(score.name);     //pangtong
    </script>
</body>
</html>
通过原型链继承,超类型实例化后的对象实例,赋值给子类型的原型属性。
子类型的原型,得到的是超类型的构造+原型里的信息。
[2] What is the result if both the instance and the prototype contain the same properties?
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>原型链继承</title>
</head>
<body>
    <script>
        function Student(){
            this.name = 'pangtong';
        }
        Student.prototype.result = 150;
        function Score(){
            this.result = 100;
        }

        Score.prototype = new Student();
        var score = new Score();
        alert(score.result);   //100
        alert(score.name);     //pangtong
    </script> 
</body>
</html>
结论:就近原则,实例里有,就返回,没有就去原型中查找。
【3】Subordination
所有的构造函数都继承自Obejct。而继承Object是自动完成的,并不需要手动继承。
经过继承后的实例的从属关系:子类型从属于自己或者他的超类型。
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>原型链继承</title>
</head>
<body>
    <script>
        function Student(){
            this.name = 'pangtong';
        }
        Student.prototype.result = 150;
        function Score(){
            this.result = 100;
        }

        Score.prototype = new Student();
        var score = new Score();
        var student = new Student();
        alert(score.result);   //100
        alert(score.name);     //pangtong

        //从属关系
        alert(score instanceof Object);          //true
        alert(score instanceof Score);           //true
        alert(score instanceof Student);         //true
        alert(student instanceof Score);         //false
    </script>
</body>
</html>
【4】Question

Inheritance also has previous problems, such as literals that override prototypes will break the relationship, use prototypes of reference types, and subtypes cannot pass parameters to supertypes. (Reference sharing and super types cannot pass parameters)

3. The technique of borrowing the constructor

       In order to solve the problems of reference sharing and the inability of supertypes to pass parameters , a technique called borrowing a constructor, or a technique called object impersonation (forged objects, classical inheritance) is used to solve these two problems.

[1] Implementation principle:

In the constructor of the subclass, use the form of apply( ) or call( ) to call the constructor of the parent class to achieve inheritance.

【2】call() method

1. Usage: The call() method calls a function with a specified this value and separately provided parameters (a list of parameters).

Syntax:
fun.call(thisArg, arg1, arg2, …)
Parameters:
1) thisArg: this value specified when the fun function runs.
It should be noted that the specified this value is not necessarily the real this value when the function is executed. If the function is in non-strict mode, the this value specified as null and undefined will automatically point to the global object (in the browser it is window object), and this value of primitive value (number, string, boolean value) will point to the automatic wrapper object of the primitive value.
2) arg1, arg2, ...: The specified parameter list.

2. Return value The
return value is the return value of the called method. If the method has no return value, it returns undefined.

3. Description The object in call()
can call the function owned by the current object. Inheritance can be achieved using call(): write a method, and let another new object inherit it (instead of writing the method again in the new object).

4. Note: The function of this method is similar to that of the apply() method, with only one difference, that is, the call() method accepts a list of several parameters, while the apply() method accepts an array containing multiple parameters.

[3] Borrowing constructor inheritance usage
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>借用构造函数继承</title>
</head>
<body>
    <script>
        function Student(age){
            this.name = ['pangtong','xiaotong'];  //引用类型,放在构造里就不会被共享 
            this.age = age;
        }
        function People(age){
            Student.call(this,age);               //对象冒充,给超类型传值
        }
        var student = new Student();
        var people = new People(18);
        alert(people.age);                       //18
        people.name.push('tongtong');            //添加的新的数据,只给子类型
        alert(people.name);                      //pangtong,xiaotong,tongtong
        alert(student.name);                     //pangtong,xiaotong
    </script>
</body>
</html>
[5] Borrowing Constructor Inheritance Disadvantages

       Although the borrowed constructor solves the problem of reference sharing and the inability to pass parameters of supertypes , it is impossible to reuse without a prototype.
       In this form of inheritance, each subclass instance will copy a method in the constructor of the parent class as the instance's own method and put it in the constructor. In the prototype, multiple instantiations are guaranteed to have only one address.
       The methods are used as the methods of the instance itself. When the requirements change and one of the methods needs to be changed, all the previous instances, their methods cannot be updated in time, and only the latter instances can access the new method.

Fourth, composition inheritance (prototype chain + constructor)

[1] Disadvantages:

The supertype is called twice during use: once when the subtype is created, and once inside the subtype's constructor.

[2] Combination inheritance usage:
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>组合继承</title>
</head>
<body>
    <script>
        function Student(name,age){
            this.name = name;
            this.age = age;
        }
        Student.prototype.run = function(){
            return this.name+ ' is running';
        }
        function People(name,age){
            Student.call(this,name,age);
        }
        People.prototype = new Student();
        var people = new People('pangtong',18);
        var people1 = new People('pangtong',18);
        alert(people.run());       //pangtong is running
    </script>
</body>
</html>

5. Prototype inheritance

[1] Concept:

This inheritance uses prototypes to create new objects based on existing ones, without having to create custom types as a result.

[2] Prototype inheritance usage
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>原型式继承</title>
</head>
<body>
    <script type="text/javascript">
        function obj(o){    //传递一个字面量函数       
            function F(){}  //创建一个构造函数(F构造是一个临时新建的对象,用来存储传递过来的对象)
            F.prototype=o;  //把字面量函数赋值给构造函数的原型
            return new F(); //最终返回实例化的构造函数
        }
        var a = {
            name:'pangtong',
            age:18,
            family:['gege','jiejie','didi']
        }
        var b = obj(a);
        alert(b.name);     //pangtong
        b.name = 'tongtong';
        alert(b.name);     //tongtong

        alert(b.family);   //gege,jiejie,didi
        b.family.push('meimei');
        alert(b.family);   //gege,jiejie,didi,meimei

        var c = obj(a);
        alert(c.name);     //pangtong
        alert(c.family);   //gege,jiejie,didi,meimei
        //引用类型共享了                           
    </script>
</body>
</html>
【3】Disadvantages

The values ​​of reference types are shared, and prototypal inheritance is generally not used alone.

6. Parasitic inheritance

[1] Concept:

The prototype + factory pattern is combined to encapsulate the process of creating objects.

[2] Parasitic inheritance usage:

function create(o) { //encapsulate the creation process
var f= obj(o);
return f;
}
//also share reference types

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>寄生式继承</title>
</head>
<body>
    <script type="text/javascript">
        function obj(o){
            function F(){}
            F.prototype=o;
            return new F();
        }
        function create(o){
            var f = obj(o);
            f.sayHello = function(){
                return this.name+this.age;
            }
            return f;
        }
        var a = {
            name:'pangtong',
            age:18,
            family:['gege','jiejie','didi']
        }
        var b = create(a);
        alert(b.name);
        alert(b.sayHello());
    </script>
</body>
</html>

7. Parasitic composition inheritance

[1] Generate background:

In javascript, compositional inheritance is the most used, but in compositional inheritance, the supertype is called twice during use: once when creating a subtype, and once inside the subtype's constructor.

[2] Parasitic combined inheritance usage:
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>寄生组合式继承</title>
</head>
<body>
    <script type="text/javascript">
        //临时中转函数
        function obj(o) {
            function F() {}
            F.prototype = o;
            return new F();
        }
        //寄生函数
        function create(box, desk) {
            var f = obj(box.prototype);
            f.constructor = desk;               //调整原型构造指针
            desk.prototype = f;
        }
        function Box(name, age) {
            this.name = name;
            this.age = age;
            this.family = ['gege','jiejie'];
        }
        Box.prototype.run = function () {
            return this.name + this.age + '运行中...'
        }
        function Desk(name, age) {
            Box.call(this, name, age);              //对象冒充
        }
        //通过寄生组合继承来实现继承
        create(Box, Desk);                          //这句话用来替代Desk.prototype = new Box();

        var desk = new Desk('tong', 100);
        alert(desk.run());          //tong100运行中
        alert(desk.constructor);    //function Desk(){}
        desk.family.push('didi');   //gege,jiejie,didi
        alert(desk.family);
        var desk1 = new Desk('pangtong',50);
        alert(desk1.run());          //pangtong50运行中
        alert(desk1.constructor);    //function Desk(){}
        alert(desk1.family);         //gege,jiejie    只共享了方法,没有共享引用
    </script>
</body>
</html>

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325496717&siteId=291194637