js面向对象

踩风火轮的乌龟 2019-10-21

一. JavaScript面向对象前言

1.1 什么是对象?

Everything is object (万物皆对象)。
对象到底是什么,我们可以从两个层次来理解。

对象的组成
    方法(有归属)----函数(自由的)
    属性(有归属)----变量(自由的)

1.对象是单个事物的抽象

一本书、一辆汽车、一个人都可以是对象,一个数据库、一张网页、一个与远程服务器的连接也可以是对象。当实物被抽象成对象,实物之间的关系就变成了对象之间的关系,从而就可以模拟现实情况,针对对象进行编程。

2.对象是一个容器,封装了属性(property)和方法(method)

属性是对象的状态,方法是对象的行为(完成某种任务)。比如,我们可以把动物抽象为animal对象,使用“属性”记录具体是那一种动物,使用“方法”表示动物的某种行为(奔跑、捕猎、休息等等)

在实际开发中,对象是一个抽象的概念,可以将其简单理解为 : 数据集或功能集。

1.2 什么是面向对象?

面向对象编程是用抽象方式创建基于现实世界模型的一种编程模式。它使用先前建立的范例,包括模块化,多态和封装几种技术。今天,许多流行的编程语言(如Java,JavaScript,C#,C+ +,Python,PHP,Ruby和Objective-C)都支持面向对象编程(OOP)。

相对于「一个程序只是一些函数的集合,或简单的计算机指令列表。」的传统软件设计观念而言,面向对象编程可以看作是使用一系列对象相互协作的软件设计。 在 OOP 中,每个对象能够接收消息,处理数据和发送消息给其他对象。每个对象都可以被看作是一个拥有清晰角色或责任的独立小机器。

面向对象程序设计的目的是在编程中促进更好的灵活性和可维护性,在大型软件工程中广为流行。凭借其对模块化的重视,面向对象的代码开发更简单,更容易理解,相比非模块化编程方法 1, 它能更直接地分析, 编码和理解复杂的情况和过程。

1.2.1 什么是面向对象编程?

面向对象编程 —— Object Oriented Programming,简称 OOP ,是一种编程开发思想。
它将真实世界各种复杂的关系,抽象为一个个对象,然后由对象之间的分工与合作,完成对真实世界的模拟。
在面向对象程序开发思想中,每一个对象都是功能中心,具有明确分工,可以完成接受信息、处理数据、发出信息等任务。
因此,面向对象编程具有灵活、代码可复用、高度模块化等特点,容易维护和开发,比起由一系列函数或指令组成的传统的过程式编程(procedural programming),更适合多人合作的大型软件项目。

1.2.2 面向对象与面向过程

    • 面向过程就是亲力亲为,事无巨细,面面俱到,步步紧跟,有条不紊
    • 面向对象就是找一个对象,指挥得结果
    • 面向对象将执行者转变成指挥者
    • 面向对象不是面向过程的替代,而是面向过程的封装
 注意:面向对象是一种通用思想,并非只在程序中使用,任何事情都可以使用----公司老板分配任务

1.3 面向对象的特点

-封装

对于一些功能相同或者相似的代码,我们可以放到一个函数中去,多次用到此功能时,我们只需要调用即可,无需多次重写。

创造对象的几种模式:单例模式,工厂模式,构造函数模式,原型模式等。

  • 继承

    子类可以继承父类的属性和方法

  • 多态(重载和重写)
    1. 重载:严格意义上说js中没有重载的功能,不过我们可以通过判断函数的参数的不同来实现不同的功能来模拟重载。
    2. 重写:子类可以改写父类的属性和方法
OOA和OOD
    OOA面向对象分析:
        人类起源:单细胞----人,进化过程中,增加了各种器官,各个器官之间分工协作
        为什么统治世界的是人类?-----精密的分工协作
        大规模分工,精密协作
    面向对象分析:将大问题拆分成小问题,并试图用分工协作来完成的思维方式。
    OOD面向对象设计:
        1.分析模块后,确定职责
            大哥招小弟--端茶倒水,点烟捶背捏脚
        2.确定耦合关系
            确定通信关系,如何交流,暗号
            弊端:当耦合达到一定程度时,如果换了一个助理,需要重新耦合,资源消耗太大
            高内聚低耦合
        3.为OOP做准备
        分析角色特性:
            讲师----技术过硬
               ----讲课技能(口才)
            销售----沟通技巧(口才)
            找到角色共同特性----继承
    对象如何被发明的?
        大量信息的处理和加工困难,打包之后,将内容包含在其中。信息传递速度更快,效率更高
    面向对象和面向 过程的区别
        面向对象--先实现功能,再运行。分工协作,同时发生,解决问题。
        面向过程--一边实现,一边运行。效率低下。
    面向对象并不是程序员发明的。在程序中我们叫面向对象(OO),在生活中叫分工协作。
    思考 > 语法

二. 对象定义的两种方式

2.1 字面量的方式进行定义

var  obj = {
                    name: "Tom ",
                    sex: " man",
                    age:19,
                    run:function(){
                        console.log("一天跑一公里");
                    }
          }

2.2 使用 new Object() 进行定义

var   obj = new  Object();
         obj.name = "Tom ";
         obj.sex = " man";
         obj.age = 19;
         obj.run = function(){
                     console.log("一天跑一公里");
         }

三. 类和对象

3.1 什么是类(Class)?

具有相同特性(数据元素)和行为(功能)的对象的抽象就是类。因此,对象的抽象是类,类的具体化就是对象,也可以说类的实例是对象,类实际上就是一种数据类型。类具有属性,它是对象状态的抽象,用数据结构来描述类的属性。类具有操作,它是对象行为的抽象,用操作名和实现该操作的方法来描述。

3.2 类和对象的区别

作为初学者,容易混淆类和对象的概念。类(Class)是一个抽象的概念,对象则是类的具体实例。比如:人是一个类,司马迁,李白,杜甫都是对象;首都是一个类,则北京,伦敦,华盛顿,莫斯科都是对象;动物猫是一个类,则Kitty、Grafield 和 Doraemon 都是对象。
我们可以说 Kitty 猫的体重是 1.5kg,而不能说猫类的体重是 1.5kg;可以说李白是诗人,而不能说人类是诗人。状态是描述具体对象而非描述类的,行为是由具体对象发出的而非类发出的。

3.3 类和对象的关系

类与对象的关系就如模具和铸件的关系,类实例化的结果就是对象,而对象的抽象就是类,类描述了一组有相同特性(属性)和相同行为的对象

class person{ }//这个是类
    $obj = new person();//类的实例化就是对象

四.创建对象的三种方式

4.1 工厂模式,使用简单的函数创建对象,为对象添加属性和方法,然后返回对象

// Class 模板
    function  Person(name,sex,age){
        var  obj = {};
        obj.name = name;
        obj.sex = sex;
        obj.age = age;
        obj.run = function(){
            console.log("每天坚持跑步");
        }
        return obj;
    }
    // 实例化
    var  person1 = Person("Tom","sex",19);
    //操作
    person1.run();  //  输出结果:每天坚持跑步

4.1.1 工厂模式的优缺点

优点:
1、 在工厂模式中,用户只需要知道所要生产的具体东西,无须关心具体的创建过程,甚至不需要具体产品类的类名。
2、 在系统增加新的产品时,我们只需要添加一个具体产品类和对应的实现工厂,无需对原工厂进行任何修改,很好地符合了“开闭原则”。
缺点:
1、 每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

 工厂模式:原料、加工、出厂
    function createPeople (name ,age ,like ){
            var obj = new Object();           //原料
            obj.name = name;                //加工
            obj.age = age;
            obj.like = like;
            obj. show = function (){
                alert( "我叫"+ this.name +",今年" +this .age+ "岁,喜欢"+ this.like)
            };
            return obj;                      //出厂
        }
        var obj = createPeople( "AAA", 23, "LOL");
        var obj2 = createPeople( "BBB", 30, "JAVA");
 
        obj.show();
        obj2.show();
    但是这种工厂模式已经被JS抛弃,
    因为JS内置了一种的工厂模式
    function CreatPeople (name ,age ,like ){
            this .name = name;
            this .age = age;
            this .like = like;
            this .show = function (){
                alert( "我叫"+ this.name +",今年" +this .age+ "岁,喜欢"+ this.like);
            }
        }
        var obj = new CreatPeople( "ABC", 20, "PHP");
        var obj2 = new CreatPeople( "QWE", 32, "Python");
        obj.show();
        obj2.show();
    JS内置的工厂模式比传统的工厂模式更高效,复用性更强。
    JS内置的工厂模式叫 构造函数。

4.2 构造函数模式。创建自定义引用类型,可以像创建内置对象实例一样使用new操作符,这种方法的缺点是,构造函数的每个成员都无法复用,每次创建出的对象都只有私有变量和私有方法,不能实现共用

//构造函数(这里就创建了一个Class模板)
    function Person(name,sex,age){
        this.name = name;
        this.sex = sex;
        this.age = age;
        this.run = function(){
            console.log("每天坚持跑步");
        }
    }
 // 实例化 ( new Object())
    var person1 = new Person("Tom","man",19);
 //操作
    person1.run();// 每天坚持跑步

4.2.1 构造函数的改进

// 构造全局的对象
    var  action = {
        run:function(){
            console.log("每天坚持跑步");
        }
    }
    //构造函数
    funcction(name,sex,age){
        this.name = name;
        this.sex = sex;
        this.age = age;
        this.run = action.run;
    }
    //实例化
    var person1 = new Person("Tom","man",19);
    person1.run();

分析: 为什么要改进构造函数?
我们都知道当实例化一个对象后,那么这个对象就拥有了模板的属性和方法,
当我们使用方法时首先会在内存中开辟一份空间,然后在执行相应的操作。假设我们实例化一万个对象,那么这一万个对象在执行方法时都要在内存中开辟空间,这样只会浪费内存的空间,这时如果能用一个操作代替一万个操作那样岂不是美哉,所以小编这里用了一个全局的对象,即使是一万个对象使用这个方法只会在内存中开辟一份空间。
但是这也有缺点,我们都知道全局变量和局部变量,全局变量易造成污染并且声明周期比较长,那么全局对象也是一样的,有没有一种方式可以不用全部对象呢?当然有,见下面的第三种创建模式

使用Json创建对象
    var obj = {
         name:"admin" ,
         age:23 ,
         like:"LOL" ,
         show:function (){
             alert("我叫" +this.name+ ",今年"+ this.age+"岁,喜欢" +this.like)
         }
    }
    obj.show()
使用构造函数创建对象
        fun ction CreatPeople( name,age ,like){
            this.name = name;
             this .age = age;
             this.like = like;
             this. show = function (){
                 alert( "我叫"+this .name+",今年" +this.age +"岁,喜欢" +this .like);
             }
         }
         var obj = new CreatPeople("ABC" ,20, "PHP");
         var obj2 = new CreatPeople("QWE" ,32, "Python");
         obj.show();
 
         obj2.show();
构造函数和对象的关系
    面向对象----对一个对象进行编程
    构造函数----提供一个对象供你编程
    通过构造函数,实现面向对象编程

4.3 原型模式,使用构造函数的prototype属性来指定共享的属性和方法,即使用构造函数定义实例属性,使用原型定义共享的属性和方法

//构造函数
    function Person(name,sex,age){
        this.name = name;
        this.sex = sex;
        this.age = age;
    }
    //使用原型对象   Object.prototype
    Person.prototype.run = function() {
        console.log("每天坚持跑步");
    }
    //实例化
    var person1 = new  Person("Tom","man",19);
    person1.run();//  每天坚持跑步

五.构造函数、原型对象、实例化对象三则的关系

首先先明白几个属性:
__proto__: 对象的原型。所有对象都有(包括函数)

prototype:函数的原型对象。只有函数(准确来说是构造函数)才有

constructor:对象上的一个属性,默认指向这个原型的构造函数
js面向对象

原型的概念
    在对象中,两个新创建的函数,是不相等的:
    var obj1 = {
        fn :function (){
            alert( 1);
        }
    }
    var obj2 = {
        fn :function (){
            alert( 1);
        }
    }
    console .log(obj1.fn == obj2.fn);     //false
 
    在构造函数中,同样属于两个新创建的函数,也是不相等的
    function Fn (name ){
        this .name = name;
        this .show = function (){
            alert( this.name);
        }
    }
    var obj1 = new Fn( "AAA");
    var obj2 = new Fn( "BBB");
    console .log(obj1.show== obj2.show);        //false
    
    此时可以看出构造函数的多次创建会产生多个同名函数,造成冗余太多。
    
    利用原型prototype解决。
     function Fn (){}
    console .log(Fn.prototype);
     // constructor表示当前的函数属于谁
    // __proto__  ==  [[prototype]],书面用语,表示原型链
     var fn1 = new Object();
    var fn2 = new Object();
    Object.prototype. show = function (){
        alert( 1);
    }
     console .log(fn1.show== fn2.show);     //ture
    此时,任何一个对象的原型上都有了show方法,由此得出,Object.prototype身上的添加的方法,相当于添加到了所有的Object身上。
    为了解决构造函数的冗余问题,我们将 属性写在构造函数内,方法写在原型中。这是面向对象的编程格式之一。
    面向对象的编程格式之一:
        1.属性写在构造函数内;
        2.方法写在原型中
        3.构造函数中的this指向当前函数同名对象
       4.原型方法中的this指向当前原型所属的函数同名对象
面向对象编程中常见概念深入解析
js面向对象

相关推荐