面对对象

130 阅读4分钟
  • 面向对象

概述

面向对象是一种变成思维(oop),主要是将对应的内容当作对象(万物皆对象)抽取里面的属性(名词)和方法(动词)。面向对象是利用万物皆对象的特点,将所有的内容都当作对象(object是所有对象的父类),进行构建。

面向对象的三大特点

  • 封装(抽取其名词为属性 动词为方法)
  • 继承(子类继承父类的非私有内容)
  • 多态(重写(子类重写父类的方法) 和 重载(一个类中又两个同名的方法(JavaScript中不存在)))

面向对象与面向过程

面向过程(关注过程实现)

例如:餐馆吃饭 打车去餐馆——服务员点餐——厨师制作——上餐——吃饭——结账

面向对象(关注对象本身)

例如:餐馆吃饭 找餐馆这个对象(点餐)—— 自己这个对象(吃饭 结账)

面向对象的核心

找专业的人做专业的事(找有这个方法的对象去调用这个方法)

对象的构建

构造函数(使用new关键词)
普通构造函数(es5)
// 无参构造
function Person(){

}
var person = new Person()
//有参构造
function Person(name){
    this.name=name//this 指向其构造的实例对象
}
var person = new Person('jack')
类的构造函数(es6)
//  类构造函数
    class Person{
    // 构造器 无参函数  被省略
    constructor(){
        }

    }
    var person = new Person()
    console.log(person)

// 有参
    class Person{
    // 构造器 有参构造
    constructor(name){
        this.name=name//this指向当前构造的示例对象
        }
        }
    var person = new Person('jack')
    console.log(person)

class与构造函数的区别(面试题)

  • 构造函数会进行预编译 class不会
  • 构造函数可以当作普通函数使用 class必须使用new关键词调用
  • class 默认采用严格模式 不允许重复命名
  • class的extend可以继承静态内容 构造函数不行
  • class中的方法都是不可枚举的(for in 不出来)

new关键词做了什么操作(面试题)

  • 自动构造对象(将当前的构造对象的原型指向其构造函数的原型)
  • 自动执行方法(手动设置属性)
  • 自动返回对象
工厂函数(调用工厂方法)
function factory(name){
    //手动创建对象
    var obj={}
    // 手动设置属性
    obj.name=name
    // 手动返回对象
    return obj
 }
    // 调用工厂函数
    var person = factory('旺财')
    console.log(person)
工厂函数的特点
  • 快速生产对象
  • 忽略特点(差异化)
  • 普通函数调用
运行流程
  • 手动创建对象
  • 手动设置属性
  • 手动返回对象

封装

抽取对应的属性和方法封装为对象,属性为名词,方法为动词

示例

class Dog{
    constructor(color,name){
            this.color = color
            this.name = name
        }
        run(){
            console.log(`${this.color}${this.name}在路上跑`)
        }
    }
var dog = new Dog('黄色','旺财')
dog.run() //黄色的旺财在路上跑

继承

  • 继承主要是子类继承父类的非私有内容,class使用extend来实现继承
  • class的extends关键词只能用于class的继承
  • 它可以继承父类的所有非私有属性及方法(包括静态属性及方法)

示例

    //class的extends关键词可以继承静态属性
    //静态属性使用static关键词声明
    class Person {
        constructor(age) {
            this.name = 'jack'
            this.age = age
        }
        sayHello() {
            console.log('你好')
        }
        static run(){
            console.log('跑')
        }
        }
        //静态属性的调用 静态属性使用类名调用
        Person.run()
        //使用extends来实现class的继承
        class Son extends Person { //Son继承Person类
            constructor(age, sex) {
            //如果想使用this
            super(age) //调用super指向对应的父类构造函数
            this.sex = sex
            }
        }
    var son = new Son(18, '男')
    console.log(son) //{name:'jack',age:18,sex:'男'} 继承了父类的name属性及age属性
    son.sayHello() //继承了父类的sayHello方法
    //类名调用 继承的静态属性
    Son.run()

多态

一个对象的多种形态的体现,主要存在两个内容,重写和重载

重载(同名不同参)

JavaScript没有重载

重载的区别
  • 通过参数个数区分

  • 通过参数类型区分

    //第一个hello方法会被第二个覆盖 无法声明同名函数 出现同名函数必覆盖
    function hello(arg){
        console.log(arg)
    }
    hello(1) // 1 undefined
    function hello(arg1,arg2){
        console.log(arg1,arg2)
    }
    hello(1,2) // 1 2
    
重写(子类重写父类)

必须基于继承关系

示例
class Animal{
    constructor(){
    }
    run(){
        console.log('某只动物在跑')
    }
    }
    class Dog extends Animal{
        constructor(name){
            super()
            this.name = name
    }
    run(){ //重写父类的方法
        console.log(`${this.name}在跑`)
    }
}
new Dog('旺财').run()
重写的好处
  • 规范代码
  • 新增提示
  • 复用代码增加其多样性