主题
ES6的Class
1、面向过程与面向对象
面向过程:面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候再一个一个的依次调用就可以了。 面向对象:面向对象是把事务分解成为一个个对象,然后由对象之间分工与合作
面向过程 | 面向对象 | |
---|---|---|
优点 | 性能比面向对象高,适合跟硬件联系很紧密的东西,例如单片机就采用的面向过程编程。 | 易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更加灵活、更加易于维护 |
缺点 | 不易维护、不易复用、不易扩展 | 性能比面向过程低 |
2、对象与类
- 对象 对象是由属性和方法组成的:是一个无序键值对的集合,指的是一个具体的事物
属性:/(常用名词) 方法:事物的行为,在对象中用方法来表示(常用动词)
- 类 在 ES6 中新增加了类的概念,可以使用 class 关键字声明一个类,之后以这个类来实例化对象。类抽象了对象的公共部分,它泛指某一大类(class)对象特指某一个,通过类实例化一个具体的对象
2.1 创建类
关键字class 语法:class 类名 { } 例如:class Star
2.2 创建的类添加属性和方法
2.2.1 类的实例添加属性的方法
通常通过在构造函数当中,通过this进行变量赋值,而this指向实例本身 关键词
js
语法:constructor(构造函数形参 ){ this. 属性1=行参;... }
constructor
它是一个构造函数 (构造函数,用来初始化属性数据:) 类的共有属性放到 constructor 里面,constructor是 构造器或者构造函数
2.2.2 类添加方法
通过 方法(形参){ 方法体 }
来定义,注意方法与方法之间不需要添加逗号 例如:sing(song){ 执行代码 }
2.3 利用类创建对象
关键字new 类生成实例,是通过 new 类名(构造函数实参)
的方式来创建 例如:var ldh = new Star(' 刘德华')
注意
- 通过class 关键字创建类, 类名我们还是习惯性定义首字母大写
- 类里面有个constructor 函数,可以接受传递过来的参数,同时返回实例对象
- constructor 函数 只要 new 生成实例时,就会自动调用这个函数, 如果我们不写这个函数,类也会自动生成这个函数
- 多个函数方法之间不需要添加逗号分隔,否则会报错
- 生成实例 new 不能省略
- 语法规范, 创建类 类名后面不要加小括号,生成实例 类名后面加小括号, 构造函数不需要加function
2.4 class类继承
Class
可以通过extends
关键字实现继承,让子类继承父类的属性和方法。extends
的写法比 ES5
的原型链继承,要清晰和方便很多。
js
class Point {
}
class ColorPoint extends Point {
}
2.4.1 类继承注意
- 继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的
- 继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法(就近原则)
- 如果子类想要继承父类的方法,同时在自己内部扩展自己的方法,利用super 调用父类的构造函数,super 必须在子类this之前调用
- 子类继承父类里面的属性和方法,子类里面可以不用有consturctor函数,但是如果有这个函数,里面必须要有super,否组会报错
- 子类构造函数中定义的变量,父类的方法中是可以通过this来访问到的,父类中的this指向子类的实例
2.4.2 为什么子类的构造函数,一定要调用super()
?
ES6 规定,若子类有constructor
构造函数,子类必须在constructor()
方法中调用super()
,且super()
必须定义在最前面,否则就会报错。这是因为子类自己的this
对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,添加子类自己的实例属性和方法。如果不调用super()
方法,子类就得不到自己的this
对象。只有super()方法才能让子类实例继承父类。
为什么子类的构造函数,一定要调用super()?原因就在于 ES6 的继承机制,与 ES5 完全不同。ES5 的继承机制,是先创造一个独立的子类的实例对象,然后再将父类的方法添加到这个对象上面,即“实例在前,继承在后”。ES6 的继承机制,则是先将父类的属性和方法,加到一个空的对象上面,然后再将该对象作为子类的实例,即“继承在前,实例在后”。这就是为什么 ES6 的继承必须先调用super()方法,因为这一步会生成一个继承父类的this对象,没有这一步就无法继承父类。
注意,这意味着新建子类实例时,父类的构造函数必定会先运行一次。
js
class Foo {
constructor() {
console.log(1);
}
}
class Bar extends Foo {
constructor() {
super();
console.log(2);
}
}
const bar = new Bar();
// 1
// 2
2.5 super
既可以当作函数使用,也可以当作对象使用。在这两种情况下,它的用法完全不同。
super( ) 作为函数调用时:
- 代表父类的构造函数。,
- super()只能用在子类的构造函数之中,用在其他地方就会报错
- ES6 要求,子类的构造函数必须执行一次super函数
- super()虽然代表了父类的构造函数,但是返回的是子类的实例,即super()内部的this指的是B的实例
super.方法名( ) super作为对象时:
- 若super在普通方法中,指向父类的原型对象(相当于Father.prototype),此时 ''定义在父类实例上的方法或属性,是无法通过super调用的''
- 在静态方法中,指向父类。
- 子类的super.只能访问父类的方法,不能访问父类的属性
- 在子类constructor中通过super调用父类的方法时,若无此方法,则为undefined,有则为此方法,方法内部的this指向当前的子类实例