一. 面向过程和面向对象的区别
-
面向过程(pop)
-
面向对象(OOP)
面向对象的特点:继承、多态、封装
4. 面向过程和面向对象的对比
优点 | 缺点 | 应用 | |
---|---|---|---|
面向对象 | 易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护 | 性能比面向过程低 | 适合程序复杂、多人合作 |
面向过程(按步骤) | 性能比面向对象高,适合跟硬件联系很紧密的东西,例如单片机就采用的面向过程编程。 | 没有面向对象易维护、易复用、易扩展 | 适合程序简单、步骤明确 |
形象比喻:用面向过程的方法写出来的程序是一份蛋炒饭 ,而用面向对象写出来的程序是一份盖浇饭。
二、ES6中的类和对象
1. 面向对象的思维特点:
- 抽取(抽象)对象共用的属性和行为组织(封装)成一 个类(模板)
- 对类进行实例化, 获取类的对象
在JavaScript中,对象是一组无序的相关属性和方法的集合 ,所有的事物都是对象,例如字符串、数值、数组、函数等。对象是一个具体的事物。
对象是由属性和方法组成的:
- 属性:事物的特征,在对象中用属性来表示(常用名词)
- 方法:事物的行为,在对象中用方法来表示(常用动词)
2. 类
1). 类constructor构造函数
constructor(方法是类的构造函数(默认方法) ,用于传递参数返回实例对象,通过new命令生成对象实例时
,自动调用该方法。如果没有显示定义,类内部会自动给我们创建一个constructor()
// 1. 创建一个明星类
class Star {
// 类的共有属性放到constructor里面
constructor(uname, age) {
this.uname = uname;
this.age = age;
}
}
//2. 利用类创建对象 new
var xz = new Star("肖战", 18);
var rb = new Star("热巴", 18);
console.log(xz);
console.log(rb);
(1)通过class 关键字创建类,类名我们还是习惯性定义首字母大写
(2)类里面有个constructor函数,可以接受传递过来的参数,同时返回实例对象
(3) constructor 函数只要new生成实例时,就会自动调用这个函数,如果我们不写这个函数,类
也会自动生成这个函数
(4) 生成实例new不能省略
(5)最后注意语法规范,创建类类名后面不要加小括号,生成实例类名后面加小括号,构造函数不需
要加function
2). 类中添加方法
class Star {
// 类的共有属性放到constructor里面
constructor(uname, age) {
this.uname = uname;
this.age = age;
sing(song) {
console.log(this.uname + song)
}
}
rb.sing("野蛮战士");
(1)我们类里面所有的函数不需要写function
(2)多个函数方法之间不需要添加逗号分隔
3. 类的继承
3.1 继承 extends
子类要继承父类的计算方法,如何?
class Father{
constructor(x, y){
this.x = x;
this.y = y;
}
sum() {
console.log(this.x + this.y);
}
}
class Son extends Father{
constructor(x, y){
??
}
}
var son = new Son(1,2);
son.sum();
3.2 super 关键字
1). super关键字用于访问和调用对象父类上的函数。可以调用父类的构造函数,也可以调用父类的普通函数
class Father{
constructor(x, y){
this.x = x;
this.y = y;
}
sum() {
console.log(this.x + this.y);
}
}
class Son extends Father{
constructor(x, y){
super(x, y); // 调用了父类中的构造函数
}
}
var son = new Son(1,2);
son.sum();
继承中的属性或者方法查找原则:就近原则
1.继承中,如果实例化子类输出一个方法,先看子类有没有这个方法, 如果有就先执行子类的
2.继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法就近原则
2). 子类继承父类方法同时扩展自己方法
super必须在子类this之前调用
class Father{
constructor(x, y){
this.x = x;
this.y = y;
}
sum(x, y) {
console.log(this.x + this.y)
}
}
//子类继承父类加法方法同时扩展减法方法
class Son extends Father {
constructor(x, y) {
//利用super调用父类的构造函数
//super必须在子类this之前调用
super(x, y);
this.x = x;
this.y = y;
}
subtract() {
console.log(this.x - this.y);
}
}
var son = new Son(5, 3);
son.subtract();
son.sum();
!! 注意:子类在构造函数中使用super,必须放到this前面(必须先调用父类的构造方法,在使用子类构造方法)
3). 使用类的注意事项
- 在ES6中类没有变量提升,所以必须先定义类,才能通过类实例化对象
- 类里面的共有属性和方法一定要加上this使用
- 类里面的this指向问题。
- constructor 里面的this指向实例对象方法里面的this指向这个方法的调用者。
class Star{
constructor(uname,age){
this.uname = uname;
this.age = age;
this.btn = document.querySelector('button');
this.btn.onclick = this.sing;
}
sing(){
console.log(this.uname);
}
}
var ldh = new Star("刘德华", 52);
var that;
var _that;
class Star{
constructor(uname, age) {
// constructor 里面的this 指向的是创建的实例对象
that = this;
console.log(this);
this.uname = uname;
this.age = age;
// this.sing();
this.btn = document.querySelector('button');
this.btn.onclick = this.sing;
}
sing(){
// 这个sing方法里面的this指向的是btn这个按钮,因为这个按钮调用了这个函数
console.log(this);
console.log(this.uname); // that里面存储的是constructor里面的this
}
dance(){
// 这个dance里面的this指向的是实例的对象ldh 因为ldh调用了这个函数
_that = this;
console.log(this);
}
}
var ldh = new Star('刘德华');