ES6中的class关键字

欢迎访问我的博客https://qqqww.com/,祝码农同胞们早日走上人生巅峰,迎娶白富美~~~

声明:本文参考业界大佬阮一峰老师的ES6标准入门

目录

  1. ES5 中的面向对象
  2. ES6 中的 class 关键字
  3. 类的实例
  4. 取值函数(getter)和存值函数(setter)
    类的继承
  5. 一些需要注意的点
  6. 不存在变量提升
  7. name
  8. Generator
  9. this
  10. 静态方法
  11. 静态属性
  12. 私有方法
  13. 私有属性
  14. 类的继承
    1. extends
    2. super

ES5 中的面向对象

// 创建一个构造函数
function People (name, age) {
    this.name = name
    this.age = age
}

// 向构造函数的原型对象中添加 say 方法
People.prototype.say = function () {
    return 'hello everyone'
}

// 实例化 People 构造函数,并保存在变量 a 中
var a = new People('zhangsan', 10)

ES6 中的 class 关键字

ES6 中的 class 类去改写上面的例子看看

class People {
    constructor(name, age) {
        this.name = name
        this.age = age
    }
    say() {
       return 'hello everyone' 
    }
}

两个例子可以说实际功能一模一样,可以看到里面有一个constructor方法,这就是构造方法,而this关键字则代表实例对象,且方法之间不需要逗号分隔,加了会报错

ES6class 类,完全可以看作构造函数的另一种写法,证明如下:

class People {  }
typeof People // "function"
People.prototype.constructor === People // true

类的实例

同样的,也是用new 关键字

class People {
    constructor(name, age) {
        this.name = name
        this.age = age
    }
    say() {
       return 'hello everyone' 
    }
}
var people = new People('zhangsan', 18)

ES5 一样,实例的属性除非显式定义在其本身(即定义在this对象上),否则都是定义在原型上(即定义在class上)

类的所有实例共享一个原型对象

class People {
    constructor(name, age) {
        this.name = name
        this.age = age
    }
    say() {
       return 'hello everyone' 
    }
}
var people1 = new People('zhangsan', 18)
var people2 = new People('zhaosi', 20)
people1._proto_ === people2._proto // true

这就意味着可以通过实例的__proto__属性为“类”添加方法

class People {
    constructor(name, age) {
        this.name = name
        this.age = age
    }
    say() {
       return 'hello everyone' 
    }
}
var people1 = new People('zhangsan', 18)
var people2 = new People('zhaosi', 20)
people1._proto_.eat = function () {
    return 'banner'
}
people1.eat() // 'banner'
people2.eat() // 'banner'

取值函数(getter)和存值函数(setter)

案例借用阮一峰老师的《ES6标准入门》

class CustomHTMLElement {
    constructor(element) {
      this.element = element;
  }

  get html() {
      return this.element.innerHTML;
  }

  set html(value) {
      this.element.innerHTML = value;
  }
}

var descriptor = Object.getOwnPropertyDescriptor(
    CustomHTMLElement.prototype, "html"
);

"get" in descriptor  // true
"set" in descriptor  // true

存值函数和取值函数是定义在html属性的描述对象上面,这与 ES5 完全一致

一些需要注意的点

不存在变量提升

类不存在变量提升

new Foo(); // ReferenceError
class Foo {}

如上代码,定义Foo在后,使用在前,则报错

name

由于本质上,ES6 的类只是ES5 的构造函数的一层包装,所以函数的许多特性都被Class继承,包括name属性

class People {}
People.name // "People"

name属性总是返回紧跟在class关键字后面的类名

Generator 方法

如果某个方法之前加上星号(*),就表示该方法是一个 Generator 函数

generator可以在执行过程中多次返回,所以它看上去就像一个可以记住执行状态的函数,利用这一点,写一个generator就可以实现需要用面向对象才能实现的功能,详细请移步廖雪峰老师的generator

class Foo {
  constructor(...args) {
    this.args = args;
  }
  * [Symbol.iterator]() {
    for (let arg of this.args) {
      yield arg;
    }
  }
}

for (let x of new Foo('hello', 'world')) {
  console.log(x);
}
// hello
// world

上面代码中,Foo类的Symbol.iterator方法前有一个星号,表示该方法是一个 Generator 函数。Symbol.iterator方法返回一个Foo类的默认遍历器,for...of循环会自动调用这个遍历器,不断返回多次,一次打印出一个参数,直到遍历出所有的参数

this

类的方法内部如果含有this,它默认指向类的实例。但是,必须非常小心,一旦单独使用该方法,很可能报错

class People {
    getPeople(name = 'zhangsan') {
        this.print(`hello ${ name }`)
    }
    print(text) {
        console.log(text)
    }
}
const people = new People()
const { getPeople } = people
getPeople() // TypeError: Cannot read property 'print' of undefined

解决办法一:在constructor中绑定this

class People {
    constructor() {
        this.getPeople = this.getPeople.bind(this)
    }
    getPeople(name = 'zhangsan') {
        this.print(`hello ${ name }`)
    }
    print(text) {
        console.log(text)
    }
}
const people = new People()
const { getPeople } = people
getPeople() // 'hello zhangsan'

解决方法二:使用箭头函数

class People {
    constructor() {
        this.getPeople = (name = 'zhangsan') => this.print(`hello ${ name }`)
    }
    print(text) {
        console.log(text)
    }
}
const people = new People()
const { getPeople } = people
getPeople() // 'hello zhangsan'

静态方法

static关键字,带有static关键字的方法不会被继承,且实例不能调用,必须用过类直接调用

class People {
    constructor(name, age) {
        this.name = name
        this.age = age
    }
    static say() {
       console.log('say everyone')
    }
}
People.say() // 'hello everyone' 
var people = new People
people.say() // TypeError: people.say is not a function

注意,如果静态方法包含this关键字,这个this指的是类,而不是实例

class People {
    static hello() {
        this.say()
    }
    static say() {
        console.log('我是静态')
    }
    say() {
        console.log('我是非静态')
    }
}
People.hello() // 我是静态

静态属性

static关键字,加在属性前面,即定义了静态属性

class Foo {
  static prop = 1;
}

私有方法

私有方法是常见需求,但 ES6不提供,只能通过变通方法模拟实现

方法一:在命名上加以区别

class People {
    // 公有方法
    foo (name) {
        this._getName(name)  
    }
    
    // 私有方法
    _getName(name) {
        return this.peop = name
    }
}

上面代码中,getName方法前面的下划线,表示这是一个只限于内部使用的私有方法。但是,这种命名是不保险的,在类的外部,还是可以调用到这个方法

方法二:将私有方法移出模块

class People {
    // 公有方法
    foo (name) {
        getName.call(this, name)  
    }
}
// 私有方法
getName(name) {
    return this.peop = name
}

上述代码中,利用call使thisfoo调用了getName方法,这使得getName实际上成为了当前模块的私有方法

私有属性

请参照http://es6.ruanyifeng.com/#docs/class

类的继承

Class 可以通过extends关键字实现继承,先看个例子

extends

// 这是父类
class Person {
  constructor(name, age){
    this.name = name
    this.age = age
  }
}

// 这是子类 美国人  可继承父类的一些属性和方法
class American extends Person {
}
const a1 = new American('Jack', 20)
console.log(a1.name) // Jack

// 这是子类 中国人  可继承父类的一些属性和方法
class Chinese extends Person{
}

const c1 = new Chinese('张三', 22)
console.log(c1.name) // 张三

super

既可以当作函数使用,也可以当作对象使用。在这两种情况下,它的用法完全不同

情况一:super作为函数调用时,代表父类的构造函数。ES6 要求,子类的构造函数必须执行一次super函数

// 这是父类
class Person {
  constructor(name, age){
    this.name = name
    this.age = age
  }

  // 打招呼 的 实例方法
  sayHello(){
    console.log('大家好')
  }
}

// 这是子类 美国人 
class American extends Person {
  constructor(name, age){
    super(name, age)
  }
}

const a1 = new American('Jack', 20)
console.log(a1)
a1.sayHello()


// 这是子类 中国人
class Chinese extends Person{
  // name 姓名 
  // age 年龄
  // IDNumber 身份证号 【中国人独有的】,既然是独有的,就不适合 挂载到 父类上;
  constructor(name, age, IDNumber){
    super(name, age)
    this.IDNumber = IDNumber
  }
}

const c1 = new Chinese('张三', 22, '130428******')
console.log(c1)
c1.sayHello()

注意

  1. 如果需要添加自己独有的属性,则不能挂在到父类上
  2. 在子类中, this 只能放到 super 之后使用

情况二:super作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类

// 这是父类
class Person {
  constructor(name, age){
    this.name = name
    this.age = age
  }

  // 打招呼 的 实例方法
  sayHello(){
    console.log('大家好')
  }
}

// 这是子类 美国人 
class American extends Person {
  constructor(name, age){
    super(name, age)
    console.log(super.sayHello())
  }
}

let amer = new American()

上面代码中,子类American当中的super.sayHello(),就是将super当作一个对象使用。这时,super在普通方法之中,指向Person.prototype,所以super.sayHello()就相当于Person.prototype.sayHello()

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

推荐阅读更多精彩内容

  • class的基本用法 概述 JavaScript语言的传统方法是通过构造函数,定义并生成新对象。下面是一个例子: ...
    呼呼哥阅读 3,962评论 3 11
  • 本文为阮一峰大神的《ECMAScript 6 入门》的个人版提纯! babel babel负责将JS高级语法转义,...
    Devildi已被占用阅读 1,927评论 0 4
  • 基本语法 简介 JavaScript语言中,生成实例对象的传统方法是通过构造函数. ES6提供更接近传统语言的写法...
    JarvanZ阅读 851评论 0 0
  • Class 的基本语法 简介 JavaScript 语言中,生成实例对象的传统方法是通过构造函数。下面是一个例子。...
    huilegezai阅读 508评论 0 0
  • 前些天路上碰到我以前的学生,也曾是我的课代表,Vivian。初中毕业后,三年高中也在本校读,可是校园内碰到的...
    筱悠漾阅读 272评论 0 0