Class
ES6当中引入了类的概念。当然类在ES6当中是基于原型的语法糖,所以,ES6中类的方法基本都可以通过原型来实现。
那么以生成一个身份证信息为例。来介绍一下ES6的类。
定义一个构造器函数 传统方式定义 function Make(name, id){ = name; = id; } Make.prototype.printName = function() { console.log(); } Make.prototype.nation = "中国"; Make.prototype.desc = "身份证生成";
ES6类的声明 class Make{ constructor(name, id) { = name; = id; } printName() { console.log(); } } Make.prototype.nation = "中国"; Make.prototype.desc = "身份证生成";
ES6当中的类像极了函数的声明。实际上
console.log(typeof Make); //function 但是实际上,class与函数声明又有本质的不同:
class 并不存在函数提升 函数可以直接调用,类声明必须使用new调用 类的继承 传统方式构造器函数继承 因为在ES6之前没有类的概念,我们更多的是使用原型继承和继承构造器函数。 在ES6之前,我们通过去集成一个构造器函数最简单的方法就是使用Parent.call(this);如下:
function Animal() { this.type = "哺乳动物" } function Dog(name) { Animal.call(this); = name; } console.log(new Dog("大黄狗")); 那么,我们的Dog构造器就继承了Animal构造器函数;Dog实例如下:
image;
ES6类的构造器函数继承 在ES6当中,继承必须使用extends关键字去继承。代码如下:
class Animal{ constructor() { this.type = "哺乳动物"; } } class Dog extends Animal{ constructor(name) { super(); = name; } } console.log(new Dog("大黄狗")); 可以看到,在ES6当中,继承一个构造器函数需要做两件事:
定义子类的时候,使用extends关键字。 在子类的构造器函数中调用super()。 这个super()实际上类似于Animal.call(this);但是又有所不同。
注意点:
super()方法必须存在且是函数调用,不然无法调用。 super()方法和call去调用有本质的不同之处。因为在类的继承当中,super()方法将会优先于Animal.call(this)执行。 原生构造器函数的继承 传统方式无法继承原生构造器函数 在ES6之前,去继承一个原生的构造器函数是做不到的。例如,我们都知道,Array是数组的构造器函数。那么,如果我们去集成这个Array的构造器函数,就可以生成一个自己的数组构造器,然后还可以添加上自己的方法。但是,这是做不到的。例如:
function MyArray() { Array.call(this,arguments); }
const myarr = new MyArray(1,2,3); MyArray.prototype = {...Array.prototype}; MyArray.constructor = MyArray; console.log(myarr);
image
结果并没有生成一个新的数组。
ES6类继承原生构造器函数 我们使用extends和super()去继承原生构造器函数,代码如下:
class MyArray extends Array{ constructor(...args) { super(...args); } }
const myarr = new MyArray(1,2,3); console.log(myarr);
image;
可以发现,我们确确实实通过了自己的构造函数生成了一个数组。那么就实现了继承原生构造器函数。我们还可以在这个子类上添加各种方法,来实现封装我们自己的数组函数。还可以调用数组上的各种快捷操作。
ES6类能继承原生构造器函数的本质原因
前面我们说过,super()方法类似于Parent.call(this);究其原因还要分析道 new 做的几件事当中去。
新生成一个对象。 将构造器函数的this指向新生成的对象。 将新生成对象通过__proto__指向构造器函数的原型。 返回新生成的对象。 在我们使用call方法去实现继承的时候,实际上,已经做到了第二件事之后。那么,在ES6之前,原生的构造器方法内部的this是不接受call方法传入的。也就是说,我们无法通过call方法去调用原生构造器上的属性和方法。导致继承失败。
在ES6的super()方法当中,super()方法将作为优先执行。那么将发生在第二件事之前。所以,相当于已经生成了一个新的数组对象,然后再将新生成对象中的this修饰为新生成的对象。那么,我就可以在这个数组对象上调用数组对象的方法了。做完这件事之后。才可以去做第二件事。这也是为什么如果没有super方法使用new会报错。因为,在没有super方法之前。第二件事也就没有办法完成,导致浏览器报错。
所以为了符合语义:
总是保证在有extends关键字的情况下使用super()方法。 super()方法写在子类构造器函数的最开头。 完成一个例子 需求:
使用类的继承,实现继承原生构造器的数组。然后通过传入电影的对象,生成数组。该实例对象具有排序方法,总是返回电影前3的电影排名。
需求代码:
const movie = new Movies({ name: "复联者联盟3", numbers: 1111 }, { name: "摔跤吧!爸爸", numbers: 998 }, { name: "捉妖记2", numbers: 1000 }, { name: "大开眼戒", numbers: 777 }, { name: "东方列车谋杀案", numbers: 2222 }); 通过传入对象,生成一个数组,该数组实现了票房数据的排序。
实现代码:
class Movies extends Array{ constructor(...movies) { super(...movies); let now = new Date(); = ${now.getMonth()+1}月${now.getDate()}日电影票房数据
}
getTop (){ return this.sort((prev, curr) => curr.numbers-prev.numbers)}getTop3 (){ let arr = this.getTop(); return arr.slice(0,3);}复制代码
}