JavaScript面向对象

1 面向过程(POP)与面向对象(OOP)

面向过程(POP):分析出解决问题需要的步骤,然后用函数把这些步骤一个个实现,使用的时候依次调用。面向过程的核心是解决问题的过程。

面向对象(OOP):把需要解决的问题分解成一个个对象,建立对象不是为了实现一个步骤,而是为了描述每个对象在解决问题中的行为,面向对象的核心是对象。

举个例子,怎样将大象装进冰箱
面向过程做法:①打开冰箱门;②将大象装进冰箱;③关上冰箱门。
面向对象要先找出对象:大象和冰箱。对于大象来说,它的功能有一个:进入冰箱。对于冰箱来说,它的功能有两个:打开与关闭,面向对象就是使用大象和冰箱的功能。

面向对象有如下优点
1、模块化更深,封装性强。
2、更容易实现复杂的业务逻辑。
3、更易维护、易复用、易扩展。

面向对象的特征如下:
1、封装性:对象是属性(静态特征)和行为(动态特征)的结合体(封装体)。
2、继承性:父类(基类)的属性和行为可以派生到子类中。子类不需要重复定义。
3、多态性:同一个消息传递给不同的对象,得到的结果不同。

2 ES6中的类和对象

2.1 类和对象概述

对象:万物皆对象,对象是一个具体的事物,看得见摸得着的事物。例如,一本书、一辆汽车、一个人可以是对象,一个数据库、一张网页、一个与远程服务器的连接也可以是对象。

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

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

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

:类抽象了对象的公共部分,它泛指某一大类。比如说在设计汽车的过程中,汽车的设计图纸就可以看作一个类,而根据该图纸生产出来的汽车就是这个类的一个一个对象。

类是具有相同属性和行为的对象的抽象,对象是类的实例(类的具体体现)。

2.2 类的基本语法

创建类时使用class关键字,并且类名习惯性首字母大写,语法为:

class 类名 {
    // 具体代码
}

利用类创建对象使用new关键字来实现,语法为:

var 对象名 = new 类名([参数]);

示例代码:创建一个Person类,并创建一个p对象

// 创建类
class Person {
}

// 创建p实例对象
var p = new Person();

在类中可以定义constructor()构造方法。constructor()方法是类的构造函数(默认方法),用于传递参数,返回实例对象,通过new命令生成对象实例时,自动调用该方法。如果没有显示定义,类内部会自动给我们创建一个constructor(),它的语法为:

class 类名 {
    constructor([参数]) { // 构造方法:用来初始化对象的成员
        // 方法体;
    }
}

示例: 创建一个Person类,并初始化对象的成员

// 创建类
class Person {
    // 定义构造方法
    constructor(name, age) {
        // this.x = x; 第一个x表示对象的属性,第二个x是传入的参数
        // this 指向创建的实例
        this.name = name;
        this.age = age;
    }
}

当使用new创建实例对象时,就会自动执行constructor(),那么参数就会传递给constructor(),从而给对象添加相关的属性,如下所示:

// 创建实例对象
var xm = new Person("小明", 10);
var xh = new Person("小红", 11);
console.log(xm); // Person { name: '小明', age: 10 }
console.log(xh); // Person { name: '小红', age: 11 }

对象成员(包括属性和方法)的访问有两种方法,在ES6中constructor()构造方法不能显式调用,具体语法如下:

// 方法一
对象名.属性名

// 方法二
对象名.方法名([参数])

示例:访问xm的姓名和年龄

xm.name // 小明
xm.age // 小红

2.3 类中的方法

为类添加方法不需要写function,多个函数方法之间也不需要加逗号分隔,具体语法为:

class 类名 {
    constructor([参数]) { // 构造方法:用来初始化对象的成员
        // 方法体;
    }
    方法名([参数]) {
        // 具体代码
    }
}

示例:为Person类添加一个say()方法并调用

class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    say(address) {
        console.log("你好,我叫" + this.name + ",我来自" + address);
    }
}

var xm = new Person("小明", 10);
var xh = new Person("小红", 11);
xm.say("北京"); // 你好,我叫小明,我来自北京
xh.say("上海"); // 你好,我叫小红,我来自上海

2.4 类的继承

在JavaScript中,继承用来表示两个类之间的关系,子类可以继承父类的一些属性和方法,在继承以后还可以增加自己独有的属性和方法。继承使用extends关键字来实现。

父类:又称为基类或超类,被继承的类
子类:又称为派生类,由父类派生来的类

语法为:

class 子类名 extends 父类名 {
    constructor() {
    }
    //其他的成员方法
}

示例代码:定义父类Father和子类Son,实现继承

class Father {
    eye() {
        console.log("我有大眼睛");
    }
}

class Son extends Father { }

// 创建子类实例对象
let s1 = new Son();
// 继承父亲的大眼睛
s1.eye(); // 我有大眼睛

2.5 super关键字

super关键字用于访问和调用对象在父类上的方法,可以调用父类的构造方法,也可以调用父类的普通方法。也就是说,super关键字代表父类,用来访问和调用父类的成员。

具体语法如下:

// 调用父类的构造方法语法
super([参数]);

// 调用父类的普通方法
super.方法名([参数])

示例代码:子类Son调用父类Father的普通方法eye()

class Father { // 父类
    eye() {
        console.log("我有大眼睛");
    }
}

class Son extends Father { // 子类
    eye() {
        super.eye();
    }
}

// 创建子类实例对象
let s1 = new Son();
s1.eye(); // 我有大眼睛

在上面的代码中,子类和父类都有eye()方法,那么在调用某个方法时,会先看子类有没有这个方法,如果有就先执行子类的方法;如果子类中没有,就会去查找父类有没有这个方法,使用就近原则。

子类在构造函数中使用super,必须放到this前面(先调用父类的构造方法,再调用子类的构造方法)。示例代码如下:

class Father {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    sum() { // 定义加和的方法sum
        console.log(this.x + this.y);
    }
}

class Son extends Father {
    constructor(x, y) {
        super(x, y); // super必须在子类的this之前调用
        this.x = x;
        this.y = y;
    }
    subtract() { // 定义一个子类特有的做减法的方法
        console.log(this.x - this.y);
    }
}

var son = new Son(10, 5); // 实例化对象
// 调用父类的加和的方法
son.sum(); // 15
// 调用自己的减法方法
son.subtract(); // 5

2.6 类中的this指向

1、constructor()构造方法中的this指向的是创建的实例对象。

// 打印构造函数中的this,得到了实例对象
class Person {
    constructor(name) {
        this.name = name;
        console.log(this); // Person { name: '小明' }
    }
}
var xm = new Person("小明");

或者可以将构造函数中的thisxm相等,输出true,所以this指向的是创建的实例对象。

var that; // 用来保存constructor中的this
class Person {
    constructor(name) {
        that = this;
        this.name = name;
    }
}
var xm = new Person("小明");
console.log(that === xm); // true

2、普通方法中的this看谁调用了这个方法,谁调用了这个方法this就指向谁。

// 实例对象调用say()方法,this指向实例对象
var that;
class Person {
    constructor(name) {
        that = this;
        this.name = name;
    }
    say() {
        console.log(this);
    }
}
var xm = new Person("小明");
xm.say(); // Person { name: '小明' }
console.log(that === xm); // true

如果在页面上写一个按钮,当点击按钮时输出当前的this值,那么最后输出的对象是该按钮,this指向了该按钮。

    <button>点击按钮</button>
    <script>
        class Person {
            constructor(name) {
                this.name = name;
                this.btn = document.querySelector("button"); // 获取按钮元素
                this.btn.onclick = this.say; // this.say后面不加(),因为要点击之后再调用
            }
            say() {
                console.log(this); // <button>点击按钮<button>
            }
        }
        var xm = new Person("小明");
    </script>

在这里插入图片描述

3 案例

设计雇员Employee类,记录雇员的情况,包括姓名、年薪、受雇时间,要求定义MyDate类作为受雇时间,其中包括工作的年、月、日,并用相应的方法(构造方法、显示信息的方法)对Employee类进行设置。

class MyDate { // 定义MyData类作为受雇时间
    constructor(year, month, date) { // 年、月、日
        //初始化对象的成员
        this.year = year;
        this.month = month;
        this.date = date;
    }
    show() { // 构造显示受雇时间的方法
        console.log(this.year + "年" + this.month + "月" + this.date + "日")
    }
}

class Employee { // 定义雇员类
    constructor(name, salary, workDate) { // 姓名、薪资、受雇时间
        this.name = name;
        this.salary = salary;
        this.workDate = workDate;
    }
    disp() { // 构造显示姓名、年薪、受雇时间的方法
        console.log("姓名:" + this.name);
        console.log("年薪:" + this.salary);
        console.log("受雇时间:");
        this.workDate.show()
    }
}

var work1 = new MyDate(2021, 6, 15); // 创建受雇时间对象
var e1 = new Employee("周瑜", 400000, work1); // 创建雇员对象
e1.disp();

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值