JavaScript ES6中的继承
- 原型继承关系图
- class方式定义类
- extends实现继承
- Babel的ES6转ES5
- 面向对象多态理解
- ES6对象增强
1. 原型继承关系图
](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/90fb1bd1e89e4f7da9ea53d3d8ba4095~tplv-k3u1fbpfcp-watermark.image?))
对象只有隐式原型,但是函数既有显式原型,又有隐式原型。
函数的隐式原型看这个函数是被谁创造出来的。
中间最上面的Function Foo()是被function Function 创建出来的,所以隐式原型__proto__指向Function的显示原型。
2.class方式定义类
在ES5中定义类使用function,在ES6中定义类使用class.
第一种方法:
1 2 3 4 5 6 7 8 9 10 11 12 13
| class Person{ constructor(name,age){ this.name = name; this.age = age; }
runing(){ console.log(this.name+"正在跑步"); } }
|
构造函数矛实例函数之间没有逗号间隔。
创建实例对象:
1 2 3 4
| var p1 = new Person("admin",12); console.log(p1.name,p1.age); p1.runing(); console.log(p1.__proto__ === Person.prototype);
|
第二种方法:
1 2 3 4 5
| var Student = class{ }
var p2 = new Student();
|
在class不支持函数的重载,也就是一个class里面只能有一个constructor函数。
class与function的不同点
- class定义的类,不能作为一个一个普通的函数去调用
2.1 class中定义访问器方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class Person { constructor(name, age) { this.name = name; this.age = age; }
set name(age) { this.age = age; }
get name() { return age; } };
|
2.2静态方法
静态方法通常用于定义直接使用类来执行的方法,不需要有类的实例,使用static关键字来定义。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class Person { constructor(name) { this.name = name; } running() { console.log(this.name + "正在奔跑"); }
static eating() { console.log("吃饭"); } }
var p1 = new Person("海绵宝宝"); p1.running(); Person.eating();
|
实例方法需要通过new关键字创建出的实例来调用,而静态方法可以直接调用。
静态方法同样也有this,谁调用这个方法,this就指向谁。
3.extends实现继承
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| class Person { constructor(name, age) { this.name = name; this.age = age; } running() { console.log(this.name + "正在奔跑"); } }
class Student extends Person { constructor(name, age, score) { super(name, age); this.score = score; }
studying() { console.log(this.name + "正在学习"); } }
class Teacher extends Person { constructor(name, age, money) { super(name, age); this.money = money; } working() { console.log(this.name + "正在工作"); } }
var stu1 = new Student("海绵宝宝", 12, 100); console.log(stu1.name, stu1.age, stu1.score); var tea1 = new Teacher("泡芙", 22, 1000); console.log(tea1.name, tea1.age, tea1.money);
|
首先定义一个父类,子类中需要用到父类的属性时,直接使用super关键字。
将共同的方法可以抽取到父类之中。
我们在继承的时候:子类 extends 父类
3.1 super关键字
class为我们的方法中提供了一个方法
- super.menthd():在子类调用父类的一个方法
- super():用来调用父类的constructor方法
注意
- 在子类中的构造方法中使用super必须在this之前,也就是说必须先通过super调用父类的构造函数。
- super的使用位置有三个:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| class Animal { constructor(name, age) { this.name = name; this.age = age; } running() { console.log("running"); } eating() { console.log("eating"); }
static sleep() { console.log("正在睡觉"); } }
class Dog extends Animal { constructor(name, age) { super(name, age); } running() { console.log(this.name + "正在奔跑"); super.running(); } static sleep() { console.log(this.name + "趴着睡觉"); super.sleep(); } }
var dog = new Dog("李长林", 23); dog.running(); dog.eating(); Dog.sleep();
|
可以看到静态方法也可以使用super。
3.2 继承内置类
我们还可以继承JavaScript内部类,比如array,我们可以在Array添加一些新方法:
1 2 3 4 5 6 7 8 9
| class ZMLArray extends Array { lastItem() { return this[this.length - 1]; } }
var arr = new ZMLArray(1, 2, 3, 4,2,1,2); console.log(arr.lastItem());
|
3.3 类的混入mixin(了解)
JavaScript继承只支持单继承。
4.JavaScript中的多态
不同的数据类型进行同一个操作,表现出不同的行为,这就是多态。
- 继承是多态的前提(实现接口)。
- 必须有父类的引用指向子类对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| class shape { getArea() {
} }
class Rectangle extends shape { constructor(width, height) { super(); this.width = width; this.height = height; } getArea() { console.log(this.width * this.height); } }
class Circle extends shape { constructor(radius) { super(); this.radius = radius; } getArea() { console.log(Math.PI * this.radius * this.radius); } }
var rect1 = new Rectangle(100, 200); var rect2 = new Rectangle(10, 20);
var c1 = new Circle(10); var ac2 = new Circle(20);
function getShapeArea(shape) { console.log(shape.getArea()); }
getShapeArea(rect1); getShapeArea(c1);
|
5. 对象字面量增强
- 属性的简写
- 方法的简写
- 计算属性名
- 解构Destrucuring:
5.1 属性的简写
当我们在对象里面写一个外部已经存在的变量时,我们可以直接使用简写。例如:
1 2 3 4 5 6 7
| var name = "hmbb"; var obj = { name, } console.log(obj.name);
|
5.2 方法的间隙
方法的简写:这种写法绑定this。
5.3 计算属性名:
1 2 3 4 5 6 7 8
| var key = "address" var obj = { [key]: "广州" } console.log(obj.address);
|
5.4 解构:
最简单的数组以及对象解构:
1 2 3 4 5 6 7 8 9 10
| var name = ["asda", "fwe", "zxcz"]; var obj = { name: "hmbb", age: 13, height: 1.99 };
var [name1, name2, name3] = name; console.log(name1, name2, name3);
var { name, age, height } = obj; console.log(name, age, height);
|
关于数组的解构
在数组里面进行解构的时候有严格的顺序问题。如果我们想要跳过一个元素:
1
| var [name1,,name3] = name;
|
也就是在跳过的元素要用逗号留出位置。
我们解构之后剩余的元素全部放到一个新数组里面。
1
| var [name1,..newArr] = name;
|
这样的结果就是name1:asda,newArr:[”fwe”,”zxcz”]。
当解构失败的时候,我们可以为这个值设置一个自定义的值。
1
| var [name1,name2,name3 = "undefined"] = name;
|
如果name3解构失败,那么它的值就是undefined。
关于对象的解构
对象的解构时没有顺序的,是根据key来进行解构的。
1 2 3
| var obj = {mame:"ada",age:12,height:1.99}; var {height,age,name} = obj;
|
对象解构是按照对象的属性名来进行一一匹配,然后解构。
将结构出来的结果,名字进行更改。
1
| var {height:gaodu,age:nianling,name:mingzi} = obj;
|
进行重命名之后,调用的时候,就使用我们重命名之后的变量名进行调用
与数组的默认值一样,当解构失败的时候,可以设置一个默认值。
1
| var {height:gaodu,age:nianling,name:mingzi,address:dizhi = undefined} = obj;
|
这个与数组解构是一样的,将没有变量存放的元素,放到一个新的对象里面。
1
| var {height,..newObject} = obj;
|
5.5解构的应用场景
- 拿到变量自动进行解构之后使用
- 对函数的参数进行解构、