面向对象
概述
面向对象是一种编程思想(oop),它主要的核心就是抽取对应的对象(封装)(万物皆对象 ),调用对象的方法。里面的主要的思维就是找有对应方法的对象做对应的事情(调用对应的方法)。
面向过程与面向对象
面向过程 (关注于过程)
去餐馆吃饭
- 出门
- 去餐馆的路上
- 进门点餐
- 厨师炒菜
- 服务员上菜
- 吃饭
- 买单
面向对象 (关注于对象)
去餐馆吃饭
- 找餐馆这个对象
对象的创建
使用new 关键词
直接调用对应的构造函数 (ES3)
//构造函数 首字母大写
function Person(name,age){
this.name = name //构造函数里面的this指向其构建的实例对象
this.age = age
}
var person = new Person('张三',18)
调用class的constructor (ES6)
class Person{
//constructor就是其构造函数
constructor(name,age){
this.name = name //constructor里面的this指向其构建的实例对象
this.age = age
}
}
var person = new Person('张三',18)
class和构造函数的区别
- class采用了严格模式 不能重复声明一个名字,而构造函数没有采用严格模式可以重复声明
- class 不会进行预编译和构造函数会进行预编译
- 构造函数可以不使用new关键词调用,而class必须使用new关键词调用(不能使用new关键词会报错)
- class 可以使用extends来实现继承 它可以继承静态属性
new关键词做了什么
- 自动构建对象 (将构造的对象的原型指向构造函数的原型)
- 自动执行构造函数 (将当前构建对象做为this传递 执行对应的构造函数)
- 自动返回对象
使用工厂函数
批量生成对象,忽略细节
function factory(name){
//手动构建对象
var obj = {}
//手动指定属性
obj.name = name
//手动返回对象
return obj
}
var newObj = factory('jack')
工厂函数和构造函数的区别
- 工厂函数批量生成 忽略细节
- 构造函数一对一生成 关注细节
面向对象的三大特性
-
封装 (抽取对应的名词为属性,动词为方法)
示例
有一只狗名字叫旺财,它会叫
class Dog{ constructor(name){ this.name = name //名词抽取为属性 } say(){ console.log(`${this.name}在叫`) //动词为方法 } } new Dog('旺财').say()练习
页面上有一个按钮上显示内容为你好 点击更改你好为不好
class Button { //按钮对象 constructor(value) { this.value = value this.init() } init(){ this.button = document.createElement('button') //按钮元素 this.button.innerText = this.value //初始化指定显示内容 document.body.append(this.button) this.handlerClick('不好') } //处理点击 this指向 handlerClick(value) { //给按钮添加事件 // 如果作为一个回调函数 或者是事件调用的函数里面的this绝对不会指向原本this 指向调用者的this let that = this this.button.addEventListener('click', function () { // this.innerText = value //里面的this 指向调用者 that.button.innerText = value }) } } new Button('你好') -
继承 (子类继承父类的非私有内容)
class Animal{ constructor(name){ this.name = name } sayHello(){ console.log('hello') } } class Person extends Animal{ constructor(name,age){ super(name) //调用父类的构造函数 里面的this会指向当前构建的实例 this.age = age } } let person = new Person('张三',18) console.log(person.age) console.log(person.name) //继承父类的属性 person.sayHello() //继承父类的方法 -
多态 (基于继承关系 子类是父类的另一种形态体现)
重写(子类重写父类的方法)
class Animal { constructor(name) { this.name = name } sayHello = () => { console.log('hello') } } class Person extends Animal { constructor(name, age) { super(name) //调用父类的构造函数 里面的this会指向当前构建的实例 this.age = age } //重写继承于父类的方法 sayHello = () => { console.log('你好') } } let person = new Person('张三', 18) person.sayHello() //继承父类的方法 进行重写 调用自身重写的方法重载 (在一个类中 有俩个同名的方法 (通过参数个数及参数类型进行区分))
重载在js中不存在 (js弱类型语句 不能强制指定类型,js的函数允许少传参及多传参,相同的变量在同一作用域内会产生覆盖)
面向对象Tab栏切换
基础切换
//构建Tab栏的类
class Tab{
constructor(nav,content){
this.nav = nav //导航栏
this.content = content //内容
this.activeIndex = 0 //激活的下标
//执行处理点击事件的方法
this.handlerClick()
}
//处理点击
handlerClick(){
//nav下面的内容添加点击
[...this.nav.children].forEach((v,i)=>{
v.addEventListener('click',()=>{
this.activeIndex = i
this.toggle()
})
})
}
//切换
toggle(){
//排他
//将选中的添加选中效果 其他移除
//移除所有的激活效果
[...this.nav.children].forEach(v=>v.classList.remove('active'))
//给对应的激活下标的添加激活效果
this.nav.children[this.activeIndex].classList.add('active');
//显示选中 隐藏未选中
//将所有的内容全部隐藏
[...this.content.children].forEach(v=>v.classList.add('hidden'))
//显示激活的
this.content.children[this.activeIndex].classList.remove('hidden')
}
}
var nav = document.querySelector('.nav')
var content = document.querySelector('.content')
//实例化对象
new Tab(nav,content)
数据渲染生成
//构建Tab栏的类
class Tab {
//传入大盒子 传入数据 [{title:'hello',content:"aa"}]
constructor(wrap, data) {
this.nav = wrap.querySelector('.nav') //导航栏
this.content = wrap.querySelector('.content') //内容
this.data = data ? data : [] //数据
this.activeIndex = 0 //激活的下标
this.init()
}
init() {
//根据data生成对应的内容
//遍历解构获取对应的值
this.data.forEach(({
title,
content
}, i) => {
this.nav.innerHTML += `
<li class=${this.activeIndex == i ? "active" : ""}>
${title}
</li>
`
this.content.innerHTML += `
<div class=${this.activeIndex != i ? "hidden" : ""}> ${content}</div>
`
})
//执行处理点击事件的方法
this.handlerClick()
}
//处理点击
handlerClick() {
//nav下面的内容添加点击
[...this.nav.children].forEach((v, i) => {
v.addEventListener('click', () => {
this.activeIndex = i
this.toggle()
})
})
}
//切换
toggle() {
//排他
//将选中的添加选中效果 其他移除
//移除所有的激活效果
[...this.nav.children].forEach(v => v.classList.remove('active'))
//给对应的激活下标的添加激活效果
this.nav.children[this.activeIndex].classList.add('active');
//显示选中 隐藏未选中
//将所有的内容全部隐藏
[...this.content.children].forEach(v => v.classList.add('hidden'))
//显示激活的
this.content.children[this.activeIndex].classList.remove('hidden')
}
}
//实例化对象
new Tab(document.querySelector('.box'), [{
title: "吃饭",
content: "<b>吃饭</b>"
}, {
title: "睡觉",
content: "<i>睡觉</i>"
}, {
title: "打豆豆",
content: "<b>打豆豆</b>"
}])