【JS5】继承有几种方式,分别是什么?

想要实现继承可以使用什么方法?

分享人:郭晨阳

目录

1.背景介绍

2.知识剖析

3.常见问题

4.解决方案

5.编码实战

6.扩展思考

7.参考文献

8.更多讨论

1.背景介绍

起源:Simula67语言

对象:“无序属性的结合,其属性值可以包含基本值、对象或者函数”。

面向对象编程(OOP):核心思想是将各种复杂关系,抽象成一个个对象,然后由对象之间的分工合作,完成对真实世界的模拟。

2.知识剖析

JavaScript语言的对象体系,不是基于“类”,而是基于构造函数(constructor)和原型(prototype)
原型对象:只要创建一个新函数,就会根据特定的规则为该函数创建一个prototype属性指向其原型对象,默认情况下原型对象会自动获得一个constructor属性,该属性包含一个指向prototype属性所在函数的指针

                Function.prototype.constructor===Function //true
            

构造函数:本身是一个函数,出于创建特定类型新对象的目的而定义的,内部使用this变量,需要和new配合使用来创建实例,this变量会绑定在实例对象上。

封装模式:将“属性”和“方法”封装成对象的模式,即创建对象的方式

                    
                    1.Object构造函数或对象字面量创建

                    var Cat = {
                 name : '',
                    color : ''
                    }

                     根据该对象的规格封装,生成两个实例对象
                    var cat1 = {}; // 创建一个空对象
                cat1.name = "大毛"; // 按照原型对象的属性赋值
                cat1.color = "黄色";
                    var cat2 = {};
                cat2.name = "二毛";
                cat2.color = "黑色";

                    
                
                    
                    原始模式的改进
                      function Cat(name,color) {
                        return {
                          name:name,
                          color:color
                        }
                      }

                      var cat1 = Cat("大毛","黄色");
                      var cat2 = Cat("二毛","黑色");
                    
                
                
                    构造函数模式
                      function Cat(name,color){
                        this.name=name;
                        this.color=color;
                      }

                      var cat1 = new Cat("大毛","黄色");
                      var cat2 = new Cat("二毛","黑色");
                      alert(cat1.name); // 大毛
                      alert(cat1.color); // 黄色
                     这是cat1、cat2会自动含有一个constructor属性,指向构造函数
                    
                
                    
                    构造函数方法很好用,但是存在一个浪费内存的问题
                      function Cat(name,color){
                        this.name = name;
                        this.color = color;
                        this.type = "猫科动物";
                        this.eat = function(){alert("吃老鼠");};
                      }

                      var cat1 = new Cat("大毛","黄色");
                      var cat2 = new Cat ("二毛","黑色");
                      alert(cat1.type); // 猫科动物
                      cat1.eat(); // 吃老鼠
                    
                
                    
                    prototype模式
                      function Cat(name,color){
                        this.name = name;
                        this.color = color;
                      }
                      Cat.prototype.type = "猫科动物";
                      Cat.prototype.eat = function(){alert("吃老鼠")};

                      var cat1 = new Cat("大毛","黄色");
                      var cat2 = new Cat("二毛","黑色");
                      alert(cat1.type); // 猫科动物
                      cat1.eat(); // 吃老鼠

                    
                
                    
                最常见方式,组合使用构造函数与原型模式
                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", 29, "Software Engineer");
                var person2 = new Person("Greg", 27, "Doctor");
                person1.friends.push("Van");
                alert(person1.friends); //"Shelby,Count,Van"
                alert(person2.friends); //"Shelby,Count"
                alert(person1.friends === person2.friends); //false
                alert(person1.sayName === person2.sayName); //true
                    
                

继承概念

许多OO语言都支持两种继承方式:接口继承和实现继承,接口继承只继承方法签名,实现继承则继承实际的方法

3.常见问题

js如何实现继承?

4.解决方案

                  
                      比如现在有一个动物对象的构造函数:
                        function Animal(){
                            this.species = "动物";
                         }

                            现在有一个猫的构造函数
                          function Cat(name,color){
                            this.name = name;
                            this.color = color;
                          }
                    
                
                    
                prototype模式

                  Cat.prototype = new Animal();
                  Cat.prototype.constructor = Cat;
                  var cat1 = new Cat("大毛","黄色");
                  alert(cat1.species); // 动物

                主要的问题是包含引用类型的值的原型属性会被所有实例共享无
                        法独立修改,并且无法想超类型中的构造函数传参。

                    
                
                    
                    构造函数绑定

                    function Cat(name,color){
                    Animal.apply(this, arguments);
                    this.name = name;
                    this.color = color;
                  }
                  var cat1 = new Cat("大毛","黄色");
                  alert(cat1.species); // 动物

                    主要的问题是如果有公用方法属性,会都被实例化,浪费内存
                    
                
                    
                    直接继承prototype

                      function Animal(){ }
                            Animal.prototype.species = "动物";

                    Cat.prototype = Animal.prototype;
                  Cat.prototype.constructor = Cat;
                  var cat1 = new Cat("大毛","黄色");
                  alert(cat1.species); // 动物

                    缺点是任何对Cat.prototype的修改都会反应到Animal.prototype,
                    并且Animal.prototype.constructor也被改变了
                    
                
                    
                        利用空对象作为中介

                        var F = function(){};
                      F.prototype = Animal.prototype;
                      Cat.prototype = new F();
                      Cat.prototype.constructor = Cat;


                        F是空对象,几乎不占内存
                    

                

5.编码实战

6.扩展思考

ES6中JavaScript拥有类的概念了,参考java等语言思考JavaScript如何使用类来简化封装、继承。

7.参考文献

参考:阮一峰的网络日志

参考:JavaScript高级程序设计第三版

8.更多讨论

继承一般用到什么地方

通常在一般的项目里不需要,因为应用简单,但你要用纯js做一些复杂的工具或框架系统就要用到了,比如webgis、或者js框架如jquery、angular、vue什么的,不然一个几千行代码的框架不用继承得写几万行,甚至还无法维护

鸣谢

感谢大家观看

BY:郭晨阳