面向对象

120 阅读5分钟

对象的重要性

js底层都是使用对象处理数据的

任何数据都有两种定义方式:字面量方式和构造函数方式(new xxx 得到是一个对象)

面向对象概念

面向对象是一种高级的编程思想

特点:

封装性 - 对象

继承性

多态性

跟面向过程对比

面向过程

更加注重中间的过程

面向对象

更加注重参与的对象,不关注过程

最佳的创建对象,添加属性,添加方法的方案

构造函数方式创建对象

字面量方式创建对象

同类型对象会重复

let wc = {
    name: '汪晨',
    gender: '男',
    age: 11
}

let xl = {
    name: '胡小龙',
    gender: '男',
    age: 12
}

let zsl = {
    name: '张胜澜',
    gender: '女',
    age: 18
}

使用工厂函数

function createObj(name, gender, age) {
    let obj = {
        name: name,
        gender: gender,
        age: age
    }
    return obj
}

// 使用对象创建对象
let zs = createObj('张三', '男', 11)
let ls = createObj('李四', '男', 12)
let ww = createObj('王五', '女', 18)
缺点

输出后无法立马看出对象的类别

使用自定义构造函数

当一个函数被new用来创建 对象了,这个函数就叫构造函数

语法:new 函数() - 返回一个对象
注意事项:

构造函数名称首字母大写

如果不传递实参,可以省略调用的小括号

function Person(){}
let p1 = new Person()
console.log(p1);

let p2 = new Person
console.log(p2);

构造函数也是函数,也能当做普通函数去调用它

function Man() {
    console.log(666);
}
let m = new Man
console.log(m);
Man()
new的时候做了什么

隐形的创建了一个空对象

将this指向他,this就代表他

执行函数中的代码

返回这个对象

添加方法

用于传递参数,将函数定义在全局,方法使用这个函数名称,将方法添加在原型上,

结论

创建对象

使用自定义构造函数

添加属性

在构造函数中给this添加

添加方法

将方法添加在原型上

原型

对象天生自带的属性__proto__,对应的值是对象

var a = {}
console.log(a);
console.log(a.__proto__);

函数天生自带的属性prototype,对应的值是对象

原型天生自带属性constructor,指的是构造函数

作用

原型中的属性和方法默认就能被对象使用

关系

构造函数比作 母

new出来的对象比作 子

原型比作 父

微信图片_20230926191009.png

给原型添加属性和方法

给原型添加 - 原型对象.方法名 = function() {}

var a = {
    name: '张三'
}
a.__proto__.eat = function() {
    console.log(666);
}
a.eat()

给原型添加eat方法 - 使用对象.__proto__添加

function Person() {
    this.name = '张三'
}
var man = new Person()
console.log(man);
man.__proto__.eat = function() {
    console.log(777);
}

通过构造函数给原型添加方法 推荐写法

function Person() {
    this.name = '张三'
}
var man = new Person()
console.log(man);
Person.prototype.eat = function() {
    console.log(888);
}
man.eat()

使用面向对象编程步骤

先定义空构造函数

new构造函数,传递实参

调用对象的方法

给原型上添加对应的方法

给构造函数根据调用语法添加形参

在构造函数中,将所有需要用到的标签获取到作为对象的属性,放在this上

给原型的方法中添加代码,实现具体效果(注意this的含义)

面向对象写tab切换案例

// 定义空构造函数
function Tab(selector) {
    // 获取大盒子
    this.box = document.querySelector(selector)
    // 根据大盒子获取其他标签
    this.ulis = this.box.querySelectorAll('ul li')
    this.olis = this.box.querySelectorAll('ol li')
}
// 给原型上添加init方法
Tab.prototype.init = function() {
    // 给标签添加事件
    for (let a = 0; a < this.ulis.length; a++) {
        // 给每一个li添加事件
        this.ulis[a].onclick = e => {
            // console.log(this); // 代表new出来的t
            for (let b = 0; b < this.ulis.length; b++) {
                this.ulis[b].className = this.olis[b].className = ''
            }
            // 给当前点击的这个li添加active类名
            this.ulis[a].className = 'active'
            // 给对应的ol中的li添加active类名
            this.olis[a].className = 'active'
        }
    }
}
// 通过构造函数创建对象
let t = new Tab('.tab')
// 调用方法实现效果
t.init()

面向对象写轮播图案例

// 1.定义空构造函数 - 定义对象,调用方法实现效果,调用方法,就需要给原型上添加对应的方法
// 定义构造函数
function Carousel(selector) {
    // 3.在构造函数中将所有需要操作的标签作为对象的属性
    this.box = document.querySelector(selector)
    this.ulis = this.box.querySelectorAll('ul li')
    this.olis = this.box.querySelectorAll('ol li')
    this.leftBtn = this.box.querySelector('.leftBtn')
    this.rightBtn = this.box.querySelector('.rightBtn')
    // 定义下标属性
    this.index = 0
    this.timer = null
}
// 给原型添加方法
Carousel.prototype.init = function() {
    // 4.将事件放在init方法中
    this.rightBtn.onclick = e => {
        // 这里的this代表c对象
        // 下标自增
        this.index++
        // 限制最大值
        if (this.index === this.ulis.length) {
            this.index = 0
        }
        // 根据下标切换图片
        // 调用轮播的核心代码
        this.move()
    }

    this.leftBtn.onclick = e => {
        // 这里的this代表c对象
        // 下标自增
        this.index--
        // 限制最大值
        if (this.index < 0) {
            this.index = this.ulis.length - 1
        }
        // 根据下标切换图片
        
        // 调用轮播的核心代码
        this.move()
    }

    for (let b = 0; b < this.olis.length; b++) {
        this.olis[b].onclick = e => {
            // this代表c对象
            this.index = b
            // 调用轮播的核心代码
            this.move()
        }
    }
    // 调用自动轮播方法
    this.auto()

    this.box.onmouseover = e => {
        clearInterval(this.timer)
    }

    this.box.onmouseout = e => {
        // 调用自动轮播方法
        this.auto()
    }
}
// 封装轮播的核心代码
Carousel.prototype.move = function() {
    // 将所有li类名去掉
    for (let a = 0; a < this.ulis.length; a++) {
        this.ulis[a].className = ''
    }
    // 给对应的图片li添加active类名
    this.ulis[this.index].className = 'active'

    // 将所有li类名去掉
    for (let a = 0; a < this.olis.length; a++) {
        this.olis[a].className = ''
    }
    // 给对应的图片li添加active类名
    this.olis[this.index].className = 'active'
}
// 给原型中再添加一个方法 - 实现自动轮播
Carousel.prototype.auto = function() {
    this.timer = setInterval(() => {
        this.rightBtn.onclick()
    }, 1000)
}
// 2.new构造函数的时候需要添加参数 - 通常是效果中最大标签选择器 - 添加形参
// new出来对象
var c = new Carousel('.carousel') // 大盒子的选择器作为实参
console.log(c);
// 调用方法实现效果
c.init()