JS面向对象编程

前言

在看本篇之前,建议知识储备需要有对象基础,可以查看链接学习对象基础

目录

前言

面对对象的理解

类的理解与创建

属性

方法

构造函数

封装

继承

多态

案例tab栏切换

面对对象的理解

        面向对象更贴近我们的实际生活, 可以使用面向对象描述现实世界事物. 但是事物分为具体的事物和抽象的事物。

     现实生活中:万物皆对象,对象是 一个具体的事物,看得见摸得着的实物。例如,一本书、一辆汽车、一个人可以是“对象”,一个数据库、一个网页。

        而在我们程序中,一切都是对象,面向对象编程,指的是程序中的所有操作都是通过对象来完成的,做任何事情都是通过对象,所有操作都是对象。

        在 JavaScript 中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串、数值、数组、函数等。

对象是由属性和方法组成的:

  • 属性:事物的 特征,在对象中用 属性 来表示(常用名词)
  • 方法:事物的 行为,在对象中用 方法 来表示(常用动词)

       我们以人为例子,属性可以类似我们的手脚,方法可以类似我们打篮球,唱,跳,rap等动作。假如我们以椅子为例子,属性可以是椅子的四个脚,椅子移动则算动作。

        假如我们给qi_bai(博主)当作一个对象,博主有名字,年龄,身高,体重等数据吧,博主还有很多功能,会吃饭,说话,那么这个对象就是表示博主,能吃饭

    const  qi_bai = {
    name:'qi_bai',
    age:19,
    height:180,
    weight:115,
    //添加方法
    eat(){
        console.log(this.name,'在eat')
    },
    say(){
        console.log(this.name,'说hello')
    }
    }

 //现在还想再来一个对象,博主带上自己的宠物小白,我们定义小白这个对象

      const  xiaoBai = {
        name:'xiao_bai',
        age:19,
        height:160,
        weight:180,
        //添加方法
        eat(){
            console.log(this.name,'在eat')
        },
        sleep(){
            console.log(this.name,'sleeping')
        }
      }
      console.log(qi_bai)
      console.log(xiaoBai)

如上操作,我们就定义完成了两个对象,我们编译后可以看到这两个对象是什么样的。

 

但是我们发现,两个对象结构类似,我们无法区分这是人还是狗,并且我们在创建的时候使用了很多代码,如果我们要创建100个类似的对象,就会很麻烦。

        这也引出几个问题,用Object创建对象,无法区分,不同类型的对象,不方便批量创建对象。

所以我们引出类这个概念。

类的理解与创建

在 ES6 中新增加了类的概念,可以使用 class 关键字声明—个类,之后以这个类来实例化对象。

  •  抽象了对象的公共部分,它泛指某一大类(class),可以指人这个大类
  • 对象 特指某一个,通过类实例化一个具体的对象,可以指博主,或者正在看文章的你
class Person {
}            //创建对象的第一步,就是通过定义类
class Dog{
}
//通过类来创建一个对象
const p1 = new Person()
const d1 = new Dog()

console.log(p1)
console.log(d1)
console.log(p1 instanceof Person)   //instanceof用来判断对象是不是由该类创建

 

        也就是说类是对象的模板,我们通过类来创建对象,比如我们定义人与狗这个对象。通过同一个类创建对象,我们称作同类对象,可以使用instanceOf来检查一个对象是否是由某个类创建。

属性

类是创建对象的模板,创建对象的第一步就是定义类,就是我们如上操作,接下来则是属性

class Person{
       
}
const p1 = new Person();
   

我们在其中添加属性等操作

p1.name = 'qi_bai'
    //    读
console.log(p1.name)

但是这样写有个问题,这样我们类与添加对象没有啥区别了,完全没有起到模板的作用,反而多了个创建类的操作,所以我们可以将属性直接定义在类中,如下

class Person{
   name
   age
   weight = '60kg'
   height = '180cm'//假如我们给height设置了值,这个就叫做实例属性
   static test ='test静态属性'
//这个叫做静态属性,console.log打印不会出现,只能通过类当中访问 
const p1 = new Person();
console.log(p1)

我们可以看到,四个属性已经被创建 ,age与name因为没有设置值所以为undefined,如果我们要读取,只需要通过对象名.属性的方法调用。这里有个test属性不能显示,因为定义了static,我们称为静态属性,当我们使用类名.静态属性名则可以调用。比如:采用 Person.test就能访问到,这种属性有两个好处,不用创建对象就能访问,假如我们用某些工具类就可以这样子创建。


 

注意: 类的代码块默认是严格模式
            类的代码是用来设置对象的属性的,可以定义对象当中有哪些属性

方法

方法就是定义在类中的函数

class Person{
    name
    sayHello = function(){
        console.log("Hello");
    }
    sayNiHao(){
        console.log("NiHao");
    }
    static sayGood(){
        console.log("Good");
        //通过类来调用
    }
}
const qi_bai = new Person();
console.log(qi_bai.name)
qi_bai.sayHello();
qi_bai.sayNiHao()
Person.sayGood();

 我们通过  对象.方法形式调用,如果方法为静态的,可以通过类名调用。

构造函数

        我们说,类的引入是为了简化创建同类对象,但是以上方法,如果创建100个Person类的对象,好像并没有简化创建。这里我们引入构造函数的概念。故名思意,这个就是一个函数,这个函数的名字为constructor,我们一开始创造对象的时候,通过设置参数,就改变了对象的name,age,与gender如下

class  Persom{
    constructor(name,age,gender){
        this.name = name;
        this.age=age;
        this.gender=gender;
    }
    sayHello(){
        console.log(this.name)
    }
}
const p = new Person('xiaoBai',8,'男')
const p1 = new Person('a',9,'男')
const p2 = new Person('x',20,'男')

//知道构造函数之后,变量就不设置值了,我们在构造函数改变我们的变量值
console.log(p)

构造函数会在我们调用类创建对象的时候执行,并且通过构造函数,我们可以很方便的创建很多同类对象。

封装

面向对象的三大特点,封装,继承和多态。

        我们平时所用的方法和类都是一种封装,当我们在项目开发中,遇到一段功能的代码在好多地方重复使用的时候,我们可以 把他单独封装成一个功能的方法,这样在我们需要使用的地方直接调用就可以了。

       但是,对象作为一种复合数据结构,负责数据存储与安全,但是我们可以直接添加或者修改属性与值到对象,这对数据安全有一定隐患,那么如何确保数据安全。我们引入私有化形式。

class Person{
#name
#age
#gender
#address = 'zj'
/*
    用#来确定私有属性,私有属性只能在某个类的内部访问
    所以保证数据的安全性,把name,age,gender换成私有属性
    但是外面访问不到这个数据,所以我们需要有个方法把数据暴露出去
    提供getter 与  setter方法开放我们对数据的操作
*/
constructor(name,age,gender){
    this.#name = name;
    this.#age = age;
    this.#gender = gender;
}
sayHello(){
    console.log('hello')
}
getName(){
    return this.#name
}
setName(name){
    this.#name=name;
}
getAge(){
    return this.#age
}
setAge(age){
    if(age>=0)
        this.#age=age
}
//默认情况下,我们的数据不是安全的,我们可以将数据类型转换成-20

get gender(){return this.#gender}
set gender(gender){this.#gender=gender}
/*
现在有个问题,我们设置了这么多有什么意义,不还是能更改数据
但getter  setter的好处
    可以控制代码的读写权限
    可以在方法中对属性值进行验证
*/
}
const qi_bai = new Person('qi_bai',19,'男');
//新的写法,用这个方法写可以在调用的时候采用p1.gender就可以获取gender属性的值

总结,封装保证了数据的安全,属性私有化,并且可以通过getter 和  setter方法来操作属性 

继承

class Dog{
    constructor(name){
        this.name = name;
    }
    sayHello(){
        console.log('旺旺')
    }
}
class Cat{
    constructor(name){
        this.name = name
    }
    sayHello(){
        console.log('喵喵')
    }
}
const cat = new Cat()
const dog = new Dog()

        如果我们像写很多关于动物的类,就无可避免去创建很多重复的代码,为了解决这个问题,我们提出继承这个概念。当一个类继承另一个类时,就相当于将另一个类中的代码复制到了当前类当中,通过继承可以减少重复的代码,在不修改一个类的前提对其进行扩展 ,使用 extends 关键字,使用类继承创建的类继承了另一个类的所有方法:

class Animal{
    constructor(name){
        this.name = name
    }
    sayHello(){
        console.log('animal')
    }
}
class Dog extends Animal{

}

class Cat extends Animal{
}
const dog = new Dog('dog1')
const cat = new Cat('cat1')
console.log(dog)
console.log(cat)
dog.sayHello();
cat.sayHello();

 我们可以看到 Cat 与 Dog类继承了Animal类,但是我们需要将Cat的方法更换成关于Cat的,我们可以重新在Cat类中创建同名方法 即可实现重写。

class Dog extends Animal{
    sayHello(){
        console.log('dog')
    }
}

class Cat extends Animal{
    sayHello(){
        console.log('cat')
    }
}

 

 如果我们想重写constructor,构造函数的第一行代码必须为super(),用于访问和调用对象父类上的函数。可以调用父类的构造函数,也可以调用父类的普通函数。

class Car {
  constructor(brand) {
    this.carname = brand;
  }
  present() {
    return 'I have a ' + this.carname;
  }
}

class Model extends Car {
  constructor(brand, mod) {
    super(brand);
    this.model = mod;
  }
  show() {
    return this.present() + ', it is a ' + this.model;
  }
}

let myCar = new Model("Ford", "Mustang");

该案例来源于w3c

多态

多态的实际含义是:同一操作作用于不同的对象上面,可以产生不同的解释和不同的执行结果。换句话说,给不同的对象发送同一个消息的时候,这些对象会根据这个消息分别给出不同的反馈。

class Person {
    constructor(name){
        this.name = name;
    }
}
class Dog {
    constructor(name){
        this.name = name;
    }
}
const dog = new Dog('xiaobai');
const person = new Person('qibai');
function sayHello(obj){
    console.log(obj.name)
}
sayHello(person);
sayHello(dog);
//以上就是多态的体现形式
//在JS中不会检查参数的类型,只要对象中有name属性就能调用这个函数

多态可以表现在重载与重写

重载:重载是有多个同名函数,但参数列表不同,调用时根据参数的多少动态匹配函数执行,比如

重写:重写是子类中定义与父类完全相同的方法以此来覆盖。

案例

tab栏切换

tab栏切换的主要功能:

  • 增删改查四大功能
  • 点击某一个tab栏,此tab栏高亮并对应的内容显示
  • 动态添加tab栏及内容
  • 点击删除某一个tab栏,此tab栏消失并内容跟着消失,高光改变
  • 双击某一tab栏,可以修改此tab栏的标题和内容

以上内容如有错误,麻烦大家在评论区指正,让我们共同进步。 加油!!!

如果对您有帮助就给一个关注支持一下吧。 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值