继承

  • ES6中的class可以看作是一个语法糖,他的绝大部分功能,ES5都 可以做到,新的class写法只是让对象原型的写法更加的清晰,更加的面向对象编程的语法而已
  • 继承顾名思义就是低级向高级获取东西,在ES6中新增一些继承的关键字,用于简化class类的操作

ES5继承

  • 基本思想:利用原型链糖一个引用类型继承另一个引用类型的属性和方法(即通过prototype和构造函数实现)
  • 实质:将父类添加到prototype原型对象上;

ES6继承:

  • 基本思想:通过exttends关键字实现继承,资料类可以继承父类中所有的方法和属性,子类必须在constructor方法中调用super方法,因为新建的子类没有自己的this对象,而是继承了父类的this对象
  • 实质:利用extends关键字继承父类,然后继承父类的属性和方法

extends关键字

使用:

  1. 解决了代码的复用性
  2. 使用extends关键字实现继承
  3. 子类可以继承父类中所有的方法和属性;
  4. 子类只能继承一个父类(单继承),一个父类可以有多个子类
  5. 子类的构造方法中必须有super()来指定调用父类的构造方法,并且位于子类构造方法中的第一行,
  6. 子类中如果与父类相同的方法和属性,将会优先使用子类的(覆盖)

代码展示:

<script>
// extends 继承对象中的属性和方法(但是不继承构造函数)
class father{
constructor( x , y){
this.x = x;
this.y = y;
};
money(){
console.log('父亲的财产!');
}
add(){
console.log(this.x + this.y);
}
}

// 1.儿子继承父亲的财产但是不能继承父亲的加法运算,因为extend关键字只能基层父亲的属性和方法,但是不能继承构造函数
class Son extends father{

}
var son = new Son();
console.log(son);
son.money();//父亲的财产!

// 2.女儿技能继承父亲的财产也可以继承父亲的加法运算,因为调用super关键字可以访问和调用对象父类上的函数。可以调用父类的构造函数,也可以调用父类的普通函数
class Girl extends father{
constructor(x , y){
super(x , y);//可以调用父亲的构造函数
}
}
var girl = new Girl(1 , 2);//3
console.log(girl);
girl.money();
girl.add();//3
</script>

结果展示:

image

super关键字

  • super关键字在类中有两种完全不同的表现形式:

1、代表函数时使用

  • ES6 要求,子类的构造函数必须执行一次super函数。代表父类的构造函数。作为函数时,super()只能用在子类的构造函数之中,用在其他地方就会报错。
  • 我们都知道,子类在继承父类的时候是存在有函数重写这一说法的,也就是说,当我们在子类当中调用构造函数的时候就会覆盖掉我们从父类当中继承过来的构造函数,父类的构造函数不执行,这时的子类就不能从父类中继承属性或方法了,因此我们需要重新调用一下父类的构造函数,也就是重新调用一次super(父类中内置的属性)来重新激活父类的继承

代码展示:

<script>
// 父亲有加法操作
class father{
constructor(x , y){
this.x = x;
this.y = y;
}
add(){
console.log(this.x + this.y);
}

}

// 儿子继承父亲的加法操作同时拓展自己的加法操作
class Son extends father{
constructor(x , y){//存在构造函数会覆盖掉父级继承过来的构造函数,因此要调用一次super
// 利用super 调用父类的构造函数
// super 必须在子类this之前调用
super();
this.x = x;
this.y = y;
}
sub(){
console.log(this.x - this.y);
}
}

var son = new Son(10 , 2);
son.add();
son.sub();
</script>

结果展示:

image

class中的getset

  • ES5一样, 在 Class 内部可以使用get和set关键字, 对某个属性设置存值函数和取值函数, 拦截该属性的存取行为。
  • getset通常用于对象的属性方法的绑定
    • get :当对目标对象的某一个属性或者方法进行获取时来去执行get绑定的一个函数
    • set :当对目标对象的某一个属性或者方法进行设置时来去执行set绑定的一个函数

代码展示:

<script>
// 与 ES5 一样, 在 Class 内部可以使用get和set关键字, 对某个属性设置存值函数和取值函数, 拦截该属性的存取行为。
// get和set通常用于对象的属性方法的绑定
// get :当对目标对象的某一个属性或者方法进行获取时来去执行get绑定的一个函数
// set :当对目标对象的某一个属性或者方法进行设置时来去执行get绑定的一个函数

// 例如:
class phone {
// 这里我用get绑定price这个属性,当这个属性被读取时就会执行get绑定的函数
// price = 100;
get price(){
console.log('价格属性被读取!');
return '价钱'//这个返回值就是price属性的值
}

// 这里我用set绑定price这个属性,当这个属性被更改(赋值)时就会执行set绑定的函数
set price(val){//切记一定要有一个形参
console.log('价格属性被修改!');
}
}

var p = new phone();
console.log(p.price);//价格属性被读取! 价钱
p.price = '免费!';//价格属性被修改!

// 使用场景:
/*
1.get常用于封装对象的动态属性,比如我们求一个总数,平均数,因为这个属性是随着数据的变化
而变化的,并不是固定的,这时我们通过这个get绑定的函数去动态的计算就会变得非常的方便!

2.set可以添加更多的控制和判断,比如我要求你输入的必须是数字,但是你输入的是字符串,这时
我们就可以做判断,成功就可已复制,失败我们就不赋值了!
*/
</script>

结果展示:

image

class中的this的指向问题

  • 1.在 ES6 中类没有变量提升,所以必须先定义类,才能通过类实例化对象,也就是说,必须要现class创建对象,才能new调用对象
  • 2.类里面的共有属性和方法一定要加this使用.
  • 3.类里面的this指向问题: constructor 里面的this指向实例对象, 方法里面的this 指向这个方法的调用者

代码展示:

<body>
<button>点击</button>
<script>
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(that.uname); // that里面存储的是constructor里面的this
}
dance() {
// 这个dance里面的this 指向的是实例对象 ldh 因为ldh 调用了这个函数
_that = this;
console.log(this);

}
}

var ldh = new Star('刘德华');
console.log(that === ldh);
ldh.dance();
console.log(_that === ldh);

// 1. 在 ES6 中类没有变量提升,所以必须先定义类,才能通过类实例化对象

// 2. 类里面的共有的属性和方法一定要加this使用.
</script>
</body>

结果展示:

image