因为之前学过类,所以听起来还比较轻松,但是初学者(以前的我 - >-)可能会有点懵逼,建议先在网上好好查阅资料
面向对象编程
面向过程编程
面向过程编程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候再一个一个依次调用就可以.面向过程,就是按照我们分析好的步骤,按照步骤解决问题
面向对象编程
面向对象是把事物分解成为一个个对象,然后由对象之间分工与合作.面向对象是以对象功能来划分问题,而不是步骤
在面向对象程序开发思想中,每一个对象都是功能中心,具有明确分工.
面向对象编程具有灵活,代码可复用,容易维护和开发的优点,更适合多人合作的大型软件项目.
面向对象的特性
- 封装性
- 继承性
- 多态性
类(class)
(仿佛回到了学Python的时候...)
在ES6中新增了类的概念,可以使用class关键字声明一个类,之后以这个类来实例化对象.
类抽象了对象的公共部分,它泛指某一大类
对象特指某一个,通过类实例化一个具体的对象.
面向对象的思维特点
- 抽取(抽象)对象共有的属性和行为组织(封装)成一个类(模板)
- 对类进行实例化,获取类的对象
创建类

创建实例
var xx = new name( )
类必须要用new实例化对象
完整写法:
class name {
// class body
}
var xx= new name();
复制
类constructor构造函数
constructor()方法是类的构造函数(默认方法),用于传递参数,返回实例对象,通过new命令生成对象实例时,自动调用该方法.如果没有显示定义,类内部会自动给我们创建一个constructor()
只要有new就会自动调用constructor( )这个方法.我创建ldh对象时将"刘德华"这个参数传递给了uname,而uname又赋值给了this.uname;this指向的是我们创建的实例,this.uname就是我创建的实例ldh的uname.我将"刘德华"赋值给我们的实例的uname,所以ldh这个实例化对象的uname就是"刘德华".(有点绕...),反正就是我创建了一个明星类,然后实例化了一个ldh对象,并且给他的uname赋值为刘德华.
注意:
- 通过class关键字创建类,类名我们还是习惯性定义首字母大写
- 类里面有个constructor函数,可以接受传递过来的参数,同时返回实例对象(所以不用return就能打印出对象)
- constructor函数,只要 new 生成实例时,就会自动调用这个函数.如果我们不写这个函数,类也会自动生成这个函数
- 生成实例new不能省略
- 最后注意语法规范,类名后面不要加小括号,生成实例,类名后面加小括号,构造函数不需要function.
类添加方法
注意: 类里面的方法不需要写function;多个方法函数之间不需要逗号分割!!
类的继承
子类可以继承父类的一些属性和方法
下面我们看看这个情况:
子类继承了父类的方法,自己重写了属性,但是想继续使用父类的方法sum()
按理来说应该得到3这个答案,但是结果是报错
这是因为我们sum()方法中的this指向的都是父类的对象,但是子类重写了,this指向的就是子类的对象了,所以当然会报错
这个时候就要用到super()了
super关键字
super关键字用于访问和调用对象父类上的函数.可以调用父类的构造函数,也可以调用父类的普通函数.
我们只要将函数这样修改就可以了
这样就可以啦
super()不仅能继承构造函数,也能继承普通函数
我们看下面的例子:
毫无疑问会输出"我是儿子?imageView2/2/w/1620",因为儿子重写了这个方法
- 继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的.
- 继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法(就近原则)
改成这样即可:
现在我们写一个子类,继承父类的加法运算,同时有自己的减法运算方法:
但是这样会报错:
在这里要注意,利用super调用父类的构造函数,super必须在子类this之前调用!!!
应修改为:
这样就没问题了
注意:
- 在ES6中类没有变量提升,所以必须先定义类,才能通过类实例化对象
- 类里面的共有的属性和方法一定要加this使用.
- constructor里面的this指向实例对象,方法里面的this指向这个方法的调用者
注意: sing这个函数如果不加括号就不会立即调用,加了就会立即调用:
比如这个方法,我们是要点击了才调用,加了就会立马调用
this指向问题
在constructor()方法中,this指向的是我们new出来的实例化对象
顺便解决了前面的问题,为什么打印出来的uname是undefined:因为this指向的是button,button的uname当然没有定义,所以就是undefined.
那要怎样才能点击button以后获取到constructor里面的uname呢?只要在外面声明一个全局变量,再将this赋值给它就可以了.
接下来就是案例时间: tab栏切换
需求:
所以我们可以先写一个Tab类出来,里面具有多种功能(方法):
获取要操作的元素
初始化绑定事件
在点击时就切换类,给点击的li和section设置类名.
我们在前面讲过,想要调用constructor()里面的属性,需要声明一个全局变量,所以我们声明一个that:
类里面的方法只能由对象本身调用,所以才要将this赋值给that
现在切换功能就基本实现了,接下来是添加功能
我们先将添加的按钮绑定事件:
接下来要做的:
初步做出来是这样的
我们先来看看效果:
肯定是有bug的,后面的新增的li并没有切换功能,且下面的内容也全部出来了,这是因为我们一开始获取的li和section都是本身存在的,初始化时都绑定了事件,但是我们后来生成的li和section都没有被获取,自然也没有绑定事件
然后在元素都添加完以后调用init初始化一遍,新增的元素就绑定了事件
那么添加功能就完成啦,现在做删除的功能
首先还是获取元素:
然后在循环中绑定事件:
编辑删除方法:
但是这个时候我们点击添加按钮时却出错了:
分析一下:
当我们页面一加载,就获取所有的关闭按钮,一开始只有三个,但是当我们点击添加按钮时,这时候调用了addTab(), addTab里面又有init(),所以当前有4个li,但是每个li都要遍历:remove的关闭按钮只有三个.
所以解决方案就是将获取关闭按钮元素的代码写在update方法里面:
然后是删除方法:
有点难qwq...最后一个短路运算也是我随便试出来的..
终于到了最后的编辑功能!
编辑事件
很幸运,section的做法和span一模一样,只要加一行代码就可以了
这个案例到这里就结束啦,真的很累,也学到了很多!!!现在看看功能
切换:
添加和删除
编辑:
困晕了,休息一下,到时候将这个案例复习一遍!(想想就好累...)