OOP

作者: 橙紫龙 | 来源:发表于2017-10-13 13:24 被阅读0次

什么是面向对象: 程序中都是用对象结构描述现实中一个具体事物

什么是对象: 程序中专门描述现实中一个具体事物的程序结构
为什么: 现实中,一个数据,必须属于某个具体对象中,才有意义。
何时: 今后,只要描述一个事物,都要将事物的属性和功能集中定义在一个对象中

如何: 面向对象三大特点:
封装,继承,多态

封装:

什么是: 创建一个对象,存储一个事物的属性和功能
其中: 事物的属性,会成为对象的属性
属性其实就是存在对象中的变量
事物的功能,会成为对象的方法
方法其实就是存在对象中的函数
功能和属性,统称为成员
为什么: 便于大量维护数据
何时: 只要使用面向对象的方式编程,都必须先将事物的属性和功能封装在对象中,再按需使用对象的属性和方法。

如何: 3种:

  1. 直接量:
    var obj={
    属性名:值,
    ... : ... ,
    方法名(){
    ... this.属性名 ...
    }
    }
    问题: 对象自己的方法,要使用自己的属性值,缺找不到!
    原因: 不加.访问的变量,只能在作用域链中查找,无法自动进入对象中查找
    解决: 错误: 在属性前加"对象."
    在对象内,禁止写死对象名
    因为对象名其实仅是一个普通变量名,很有可能发生变化
    正确: 用this.属性名:
    this: 在函数执行时,自动创建的一个关键词
    自动指向正在调用当前函数的.前的对象
    为什么: 不受对象名的影响
    总结: 今后,只要对象自己的方法,想访问自己的属性,必须用this.属性名
var lilei=/*new */Object();
       lilei.sname="Li Lei";
       lilei.age=11;
       lilei.intr=function(){
           console.log(
                   "I'm "+this.sname
                   +", I'm "+this.age
           );
       }

       console.dir(lilei);//显示一个对象的存储结构
       console.log(lilei.sname);
       console.log(lilei.age);
       lilei.intr();//this->lilei
       lilei.age++;
       console.log(lilei.age);
       lilei.intr();
       lilei.sname="Li Xiaolei";
       lilei.intr();
  1. 用new: 2步:
  1. 先创建一个空对象
    var obj=new Object(); //new可省略,()也可省略,但不能同时省
  2. 向空对象中添加新成员:
    obj.属性名=值;
    obj.方法名=function(){ ... this.属性名 ... }
    说明: js中的对象,可随时,通过强行赋值的方式,添加新成员
    何时: 如果在创建对象时,暂时不知道对象的成员

揭示: js中的对象,底层其实就是关联数组

  相同: 1. 都可用.或[]随时添加/访问成员
       2. 访问不存在的成员,不报错,返回undefined
       3. 都可用for in遍历每个成员
  不同: 对象比关联数组用法简单!

今后,都是用对象来代替关联数组使用!

console.dir():xianshi

问题: 一次只能创建一个对象
如果反复创建相同结构的多个对象,重复代码会很多
解决:构造函数

//DRY
        //1. 定义构造函数,描述学生类型的统一结构
        function Student(sname,age){
            this.sname=sname;
            this.age=age;
            this.intr=function(){
                console.log(
                    "I'm "+this.sname
                    +", I'm "+this.age);
            }
        }
        //2. 用new调用构造函数反复创建学生类型的具体对象
        var lilei=new Student("Li Lei",11);
        var hmm=new Student("Han Meimei",12);
        console.dir(lilei);
        console.dir(hmm);
        lilei.intr();
        hmm.intr();
  1. 用构造函数(constructor):
    什么是: 描述同一类型的多个对象,相同成员结构的函数
    第二个作用: 将一个空对象构造为拥有属性和功能的完整对象
    何时: 只要反复创建同一类型的多个对象时,都要先用构造函数描述统一的结构,再用构造函数创建对象
    如何: 2步
1. 定义构造函数: 
  function 类型名(属性参数,....){
    this.属性名=属性参数;
       ... = ... ;
    this.方法名=function(){
      ... this.属性名 ...
    }
  }
2. 使用构造函数反复创建对象: 
  var obj= new类型名(属性值,...);
 调用时的参数值,应和定义构造函数时的属性参数保持一致。
 new: 4件事: 
 1. 创建一个新的空对象
 2. 自动让新的子对象继承构造函数的原型对象
 3. 调用构造函数,将构造函数中的this执行正在创建的新对象。向新的空对象中强行添加新成员
 4. 将新对象地址返回给变量保存

优: 重用结构定义
缺: 浪费内存

构造函数ex:
function Student(sname,age){
        this.sname=sname;
        this.age=age;
        this.intr=function(){
            console.log("我是"+this.sname+",我今年"+this.age);
        }
    }
    var lilei=new Student("Li lei","18");
    console.log(lilei);
    lilei.intr();
    var Hanmeimei=new Student("Hanmeimei","21");
    Hanmeimei.intr();

继承:

什么是: 父对象的成员,子对象无需创建即可直接使用!
为什么: 代码重用!节约内存!
何时: 所有子对象都拥有相同的属性值和方法定义时,都要用继承来实现
如何: js中所有继承,都是继承原型对象

什么是原型对象: 集中存储所有子对象共有成员的父对象
为什么: 实现继承
何时: 只要实现继承,都要继承原型对象
如何:
创建: 不用手动创建,买一赠一
其实创建构造函数同时,都附赠一个空的原型对象

继承: 不用手动设置

用new创建新的子对象时,会自动设置新对象继承构造函数的原型对象

添加共有成员: 

  构造函数.prototype.成员=值;

总结: 只要所有子对象共用的成员,都必须集中存储在原型对象中


自有属性和共有属性:

自有属性: 直接保存在对象本地的属性

共有属性: 保存在原型对象中,所有子对象共有的属性

读取: 两者完全一样: 对象.属性名

修改: 自有属性: 只能用子对象改: 子对象.自有属性名=值

自有、共有属性修改时的差别:!!!
lilei.sname="li xiaolei"
Student.prototype.className="初二";

共有属性: 只能用原型对象修改:

                        构造函数.prototype.共有属性名=值

原型链: prototype chain

什么是: 由多级父对象,逐级继承,形成的链式结构

为什么: 为了更高级,更大范围的重用

如何:

所有对象,都有__proto__属性

原型对象的__proto__指向更上级的父对象

所有对象最终都继承自Object.prototype——顶级父对象

内置对象的原型链:

其实每种内置类型都有对应的构造函数和原型对象,也最终都继承自Object.prototype

其中: 内置类型的构造函数负责创建该类型的子对象

内置类型的原型对象负责保存该类型所有子对象共有的API

问题: 旧浏览器不支持新的API

解决: 向旧浏览器中的原型对象中手动添加一个函数

鄙视: 判断一个对象是不是数组类型,有几种方法:

typeof不行!

  1. 判断原型对象:
Object.getPrototypeOf(obj)==Array.prototype   

      判断obj是数组类型的子对象

 问题: __proto__是内部属性,本不应该被访问到

 解决: 用Object.getPrototypeOf(obj)

代替proto

  1. 判断构造函数:

实例

obj instanceof Array

判断obj是不是被构造函数Array创造出来的

instanceof 不仅判断直接父类型,而是所有在原型链上的类型,都返回true!

  1. 判断对象的内部class属性
每个对象内部,都有一个隐藏的class属性,记录该对象创建时的数据类型

class属性不会随继承关系的改变而改变

问题1: class是内部属性

解决: 只有最顶层的toString()才能输出对象的class属性值

[object class名]

问题2: 内置类型的原型对象中几乎都重写了新的toString()

解决: 用call强行调用: 

call: 让一个对象,调用一个本来无法调用到的函数

何时: 只要希望调用一个本无法调用到的函数

如何: 要调用的函数.call(对象)

Object.prototype.toString.call(obj)=="[object Array]"

说明obj的内部属性class的值为"Array"

  1. 多态:

什么是: 同一个函数在不同情况下表现出不同的状态

重写: 如果子对象觉得父对象的成员不好用,可在本地定义同名成员,覆盖父对象中继承来的成员

为什么: 体现子对象和父对象之间的差异

何时: 只要子对象觉得父对象的成员不好用,就可以重写!

相关文章

  • OOP

    oop_simplestclass.py oop_methond.py oop_init.py oop_objva...

  • 关于oop和aop

    oop oop(Object Oriented Programming)面向对象编程, oop的设计特征:封装, ...

  • 面向对象编程

    OOP 指什么?有哪些特性 OOP:OOP(Object-oriented programming, 面向对象编程...

  • 关于对象-原型

    1.OOP 指什么?有哪些特性 OOP:Object-oriented programming,缩写OOP,即面向...

  • Java面试总结

    1.什么是OOP、AOP OOP即面向对象编程OOP三大特征:封装、继承、多态OOP五大原则:单一职责原则 (Si...

  • OOP

    类定义 说明:init为构造函数,第一个参数为self为函数本身。类成员以双下划线开头,说明为private访问限...

  • OOP

    java in think 起因 自从买了Java in think 这本书,一直想认真仔细的品味下这本某种意义的...

  • oop

    面向对象基本操作:一:基本操作示例一: class Test_A(): #定义类名def A(self):...

  • OOP

  • OOP

    Great work! Let's review everything that we've learned ab...

网友评论

      本文标题:OOP

      本文链接:https://www.haomeiwen.com/subject/zgppyxtx.html