ES6提供了更接近传统的语言的写法,所以引入了Class(类)这个概念,作为对象的模板。通过Class关键字,可以定义类。这个就有点想java了,大家说有没有?
其它在Class出现之前其可以实现的功能在ES5版本的时候就可以实现绝大部分的功能了,而这个class写法只是让对象原型的写法更具清晰,更具面向对象编程的语法而已。
如果想要看ES5中的对象构造函数,以及原型,原型链可以看一下前面。对象构造函数,以及原型以及原型链。
所以现在开始引用了,不再具体阐述了,看如下演示:
构造函数
按照以前ES6版本之前声明一个对象:
function Car( brand ,price) {
this.brand=brand;
this.price=price;
}
// 为什么这样方法直接写在原型上而是写在构造函数,可以看下后面Class对象后截图就明白了
Car.prototype.drive=function () {
console.log('这个车真的可以刹车,而且刹得住');
}
var car=new Car('锤子','30万');
car.drive();// 这个车真的可以刹车,而且刹得住
这样看的话其实如果了解JavaScript的原型的话,很容易看明白,但是相对于Class却更具明了:
class Car{
constructor(brand ,price) {
this.brand=brand;
this.price=price;
}
// 这里需要如下写,而不能按照是 ES5中那样 dirve:function(){}
drive(){
console.log('这个车真的可以刹车,而且刹得住');
}
}
var car=new Car('锤子','30万');
car.drive();//这个车真的可以刹车,而且刹得住
是不是使用了新特性Class后,让人看着只是会明了。(但是不得不说一句话,毕竟编程语言都是老外创建的,所以老外的编程语言对于会英语的人太友好了,直接告诉你constructor就是构造函数。)
可以看出在Class中的的方法会默认在其生成的对象的_proto_
上,所以上面在写方法的时候卸载类的原型上。
静态成员
说起静态成员的话,在Java中相对来说很容易理解,但是在ES6之前就需要绕过一个弯才能理解一些。
ES5之前的静态成员
function Car(){
}
Car.brand="锤子汽车";
Car.drive=function(){
console.log('这个车真的可以刹车,而且刹得住');
}
Car.prototype.price='30万';
var car=new Car();
可以看出对于构造函数直接赋值成员,而这个成员却在创建的car中却拿不到(这个其实和java有些不同,java中的却是new 对象和对象类本身都可以拿到
)。而这种成员(属性或方法)被称之为静态成员。
如果看ES5看的话有些懵,需要绕一圈理解,但是理解了也觉得不错可以接受。但在ES6中却更具容易理解:
class Car{
//普通属性
price='30万';
// 静态成员
static brand='锤子汽车';
static drive(){
console.log('这个车真的可以刹车,而且刹得住');
}
}
可以看出ES6的话看着会更具清楚明白什么是静态。当然如果调用静态成员之恩呢通过类调用而不是new的对象来调用。
所以:类(class)通过 static关键字定义静态方法。不能在类的实例上调用静态方法,而应该通过类本身调用。这些通常是实用程序方法,例如创建或克隆对象的功能。
所以静态方法通常用于创建实用程序函数。
说两个静态方法特点:
-
静态方法调用同一个类中的其他静态方法,可使用 this 关键字。
class StaticMethodCall { static staticMethod() { return 'Static method has been called'; } static anotherStaticMethod() { return this.staticMethod() + ' from another static method'; } } StaticMethodCall.staticMethod(); // 'Static method has been called' StaticMethodCall.anotherStaticMethod(); // 'Static method has been called from another static method'
-
非静态方法中,不能直接使用
this
关键字来访问静态方法。而是要用类名来调用CLASSNAME.STATIC_METHOD_NAME()
,或者用构造函数的属性来调用该方法:this.constructor.STATIC_METHOD_NAME()
.class StaticMethodCall { constructor() { console.log(StaticMethodCall.staticMethod()); // 'static method has been called.' console.log(this.constructor.staticMethod()); // 'static method has been called.' } static staticMethod() { return 'static method has been called.'; } }
如果调用静态的调用非静态的呢?
class StaticMethodCall { noStatic() { console.log('method has been called.') } static staticMethod() { StaticMethodCall.prototype. noStatic(); this.prototype. noStatic(); } }
为什么这样掉,因为类也无法直接调用非静态方法。
继承
这个在聊原型以及原型链的时候聊过,这个继承的问题,还是老规矩先看一个以前版本的再来一个ES6版本之后的。
ES5版本的继承:
function Car( brand ,price) {
this.brand=brand;
this.price=price;
}
// 为什么这样方法直接写在原型上而是写在构造函数,可以看下后面Class对象后截图就明白了
Car.prototype.drive=function () {
console.log('这个车真的可以刹车,而且刹得住');
}
function electricCar( brand ,price,automatic) {
Car.call(this,brand,price)
this.automatic=automatic;
}
electricCar.prototype=new Car;
electricCar.prototype.auto=function(){
console.log('我可以自动驾驶');
}
其实对于这种继承关系,需要在原型以及原型链的理解上看着觉得的确是一种继承关系,说实话如果第一眼看觉得会懵,而如果对JavaScript的原型链理解了也觉得哦,是这样。
在在ES6中的继承有了extends这个关键字,还有调用父类的super这个关键字,这两个的结合说实话让很多编程语言者再看JavaScript的时候会觉得这个才是真的爽。
class Car{
constructor(brand,price){
this.brand=brand;
this.price=price;
}
drive(){
console.log('这个车真的可以刹车,而且刹得住');
}
}
class electricCar extends Car{
constructor(brand,price,automatic){
super(brand,price);
this.automatic=automatic;
}
auto(){
console.log('我可以自动驾驶');
}
}
这样看是否不是觉得明了了很多,直接就可以感受到继承。
重写
重写说白了就是重新父类的方法,如果不重写直接调用父类的方法,如果重写了就是走自己的方式。
这个还是老规矩分两个部分,一个是ES6之前的的一个ES6版本的类写法。
function Car( brand ,price) {
this.brand=brand;
this.price=price;
}
// 为什么这样方法直接写在原型上而是写在构造函数,可以看下后面Class对象后截图就明白了
Car.prototype.drive=function () {
console.log('这个车真的可以刹车,而且刹得住');
}
function electricCar( brand ,price,automatic) {
Car.call(this,brand,price)
this.automatic=automatic;
// 可以这样写,但是还是按照习惯写所以这个地方只是演示
// this.drive=function(){
// console.log('自动驾驶,还需要手动刹车');
// }
}
electricCar.prototype=new Car;
electricCar.prototype.auto=function(){
console.log('我可以自动驾驶');
}
// 按照习惯写
electricCar.prototype.drive=function(){
console.log('自动驾驶,还需要手动刹车');
}
现在看一下ES6的写法,也是很直接,让人看着相对更加好理解。
class Car{
constructor(brand,price){
this.brand=brand;
this.price=price;
}
drive(){
console.log('这个车真的可以刹车,而且刹得住');
}
}
class electricCar extends Car{
constructor(brand,price,automatic){
super(brand,price);
this.automatic=automatic;
}
auto(){
console.log('我可以自动驾驶');
}
drive(){
console.log('自动驾驶,还需要手动刹车');
}
}
是不是看着更具好理解?看结果
对象中的set和get
聊这个的相对说有一点赋值,再ES6中相对来说容易一些,而再ES6之前的版本就需要了解一个深的对象方法:Object.defineProperty。这个到时候单独看一篇聊,现在只是简单的呈现一下,对比看以下。
var pattern = {
get: function () {
return '获得属性调用这个方法';
},
set: function (val) {
this.price = val;
}
};
function Car() {
Object.defineProperty(this, 'brand', pattern);
}
var car = new Car();
car.brand = 'test';
console.log(car.brand);
console.log(car.price);
可以看出这个时候通过 Object.defineProperty修改赋值和得到值的结果。而这个再很多逆向JavaScript的时候通过这个方式进行hook,还是那句话后面单独聊这个Object这个方法。
现在看一下ES6中的set和get方法的呈现:
class Car{
get brand(){
return '获得属性调用这个方法';
}
set brand(val){
this.price = val;
}
}
var car = new Car();
car.brand = 'test';
console.log(car.brand);
console.log(car.price);
可以看出ES6中看的话会更具明了。
本篇就是简单的聊了以下ES6中的calss这个类的一些知识,希望对大家有帮助。