ES6 class和面向对象编程

在ES5中,我们经常使用方法或者对象去模拟类的使用,并基于原型实现继承,虽然可以实现功能,但是代码并不优雅,很多人还是倾向于用 class 来组织代码,很多类库、框架创造了自己的 API 来实现 class 的功能。
ES6 时代终于有了 class (类)语法,能让我们可以用更简明的语法实现继承,也使代码的可读性变得更高,同时为以后的JavaScript语言版本添加更多的面向对象特征打下基础。
一、 类的定义

  1. ES5使用函数模拟类
function Person( name , age ) {
    this.name = name;
    this.age = age;
}
Person.prototype.say = function(){
    return '我叫' + this.name + ',今年' + this.age + '岁';
}
var  p = new Person('xiaoming',33);  // Person {name: "xiaoming", age: 33}
p.say();

使用ES5语法定义了一个Person类,该类有name age food三个属性和一个原型eat方法。

2.ES class定义类

class Person{
    constructor(name,age){
        this.name = name;
        this.age = age;
    }
    say(){
        return '我叫' + this.name + ',今年' + this.age + '岁';
    }
}
var stu = new Person("xiaoming",22);
p.say();

上面代码定义了一个同样的Person类,constructor方法就是构造方法,而this关键字则代表实例对象;
注:虽然ES6引入了class关键字,但并没有真的引入类这个概念,通过class定义的仍然是函数,数据类型中也没有class类型。

console.log(typeof Person);//还是'function'

所以说,class仅仅是通过更简单直观的语法去实现原型链继承。这种对语言功能没有影响、但是给程序员带来方便的新语法,被称为语法糖。

二、类的传参
在类的参数传递中,我们在constructor( )进行传参,传递参数后可以直接使用this.xxx进行调用。

class Person{
    constructor(x,y){
        this.x = x;
        this.y = y;
    }
    add(){
        return this.a + this.b;
    }
}
let stu = new Person(11,22);
stu.add();//11+22=33

用constructor来传递参数,然后用了一个add方法,把参数相加。

三、静态方法

  1. 使用函数模拟类时,通过函数名.静态方法名,来定义静态方法:
function Person(name,age){
    this.name = name;
    this.age = age;
    Person.say = function(){
        return "I can say!"
    }
}
Person.say();//I can say!
var student = new Person("xiaoming",11);
student.say();//报错

静态方法是不需要实例化,可以通过类名直接调用,注意的是静态方法不会继承到类实例中,因此静态方法经常用来作为工具函数。比如我们经常用的Math.random()。

  1. 在ES6 class类定义中,可以使用static关键字定义静态方法:
class A{
    constructor(){};
    static say(){
        console.log("I can say!");
    }
}
A.say();//I can say
var a = new A();
a.say()//error

跟之前一样,通过类名直接调用,不会继承到类实例中。
static关键字是ES6的另一个语法糖,static 使静态方法声明也成为了一个一等公民。

四、封装和继承

  1. ES6之前子类对象是通过使用原型来实现继承父类,子类函数和父类函数共享原型的形式来实现:
function Person(name,age){
    this.name = name;
    this.age = age;
}
function father(name,age,firstname,lastname){
    Person.call(this,name,age);//通过call来继承父类的方法来实现自己的功能
    this.lastname = lastname;
    this.firstname = firstname;
}
console.log(new father('zhangsan',11,'zhang','san'));
//father {name: "zhangsan", age: 11, lastname: "san", firstname: "zhang"}
function son(name,age,firstname,lastname){
    father.call(this,name,age,firstname,lastname);
};
son.prototype = Object.create(father.prototype);
son.constructor = son;
console.log(new son('zhangsi',5,'zhang','si'));
//son {name: "zhangsi", age: 5, lastname: "si", firstname: "zhang"}
  1. ES6中新的extends关键字解决了这个麻烦问题:
语法:class son extends father{}

下面定义了一个Child类,该类通过extends关键字,继承了Parent类的所有属性和方法。

class Parent{
    constructor(firstname,lastname){
        this.firstname = firstname;
        this.lastname = lastname;
    }
}
class Child extends Parent{
    constructor (firstname,lastname,name){
        super(firstname,lastname);
        this.name = name;
    }
    say(){
        console.log("I can say!")
    }
}
console.log(new Child("蒙奇","D","路飞"));
//Child {firstname: "蒙奇", lastname: "D", name: "路飞"}
  1. super关键字
    super表示超,超类,父类。既可以当作函数,也可以当作对象使用。
    (1)super作为函数调用,代表父类的构造函数。
    注意,ES6中规定,子类的构造函数必须执行一次super函数。格式:
class Parent{}
class Child extends Parent{
    constructor (){
        super();
        // ...
    }
    // ...
}  
class Parent{}
class Child extends Parent{
    constructor (){
        // super();  如果调用super,程序会报错Uncaught ReferenceError: this is not defined
        // ...
    }
    // ...
}
new Child();

注意,super虽然代表父类中的构造函数,但是返回的是子类的实例,即super内部的this指的是子类Child,在这种情况下,super()相当于Parent.prototype.constructor.call(this)。
(2)super作为对象,代表父类的原型对象。

class Parent{
    constructor(firstname,lastname,age){
        this.firstname = firstname;
        this.lastname = lastname;
        this.age = age;
    }
    say(){
        console.log("I can say.");
    }
}
class Child extends Parent{
    constructor (firstname,lastname,age,score){
        super(firstname,lastname,age); //super在这里代表父类的构造函数 
        this.score = score;
        super.say();//super在这里代表父类的原型对象,可以调用父类的方法
    }
    
}

console.log(new Child("蒙奇","路飞",18,100));
// I can say.
// {firstname: "蒙奇", lastname: "路飞", age: 18, score: 100}

使用extends关键字实现继承,那么子类中可以通过super关键字调用父类的东西
(3)4.3 getter(取值)、 setter(存值)
与 ES5 一样,在“类”的内部可以使用get和set,对某个属性设置存值函数和取值函数,拦截该属性的存取行为。

class Parent{
    constructor(){}
    get firstname(){
        return "D.";
    }
    set lastname(value){
        console.log('我的名是:' + value);
    }
}

let p = new Parent();
console.log(p.firstname);//D.
console.log(p.lastname = "路飞")  ;
//我的名是:路飞
//路飞

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,290评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,107评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,872评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,415评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,453评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,784评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,927评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,691评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,137评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,472评论 2 326
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,622评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,289评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,887评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,316评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,490评论 2 348

推荐阅读更多精彩内容