0%

es6-class

ES6 Class 语法糖,任然是通过 构造函数 创建实例的

ES5 创建一个类

1
2
3
4
5
6
7
8
9
10
11
12
13
// ES5 构造函数创建
function Point (x, y) {
this.x = x
this.y = y
}

Point.prototype.getPosition = function () {
return '(' + this.x + ', ' + this.y + ')'
}

var p1 = new Point(10, 20)
console.log(p1) // Point { x: 10, y: 20 }
console.log(p1.getPosition()) // (10, 20)

ES6 Class

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
// ES6 class 定义 类
class Point {
z = 0 // 可以直接声明构造函数属性,

// 构造函数 不写为空 constructor() {}
constructor (x, y, z) {
this.x = x
this.y = y
this.z = z

// 当自定义返回值,则 对象 p1 不再是 构造函数的实例
// return { a: 'a' }
}
getPosition () {
return `(${this.x}, ${this.y})`
}
// 静态方法
static getClassName () {
return Point.name // 每一个 class 都有一个 name 属性,如同 每个函数都有 name
}
}

const p1 = new Point(1, 23)
console.log(p1) // Point { z: 3, x: 1, y: 2 }
console.log(p1.getPosition()) // (1, 2)

// console.log(p1 instanceof Point) // false

console.log(p1.hasOwnProperty('x')) // true 构造函数上
console.log(p1.hasOwnProperty('getPosition')) // false
console.log(p1.__proto__.hasOwnProperty('getPosition')) // true 实际 在 原型上

// console.log(p1.getClassName()) // p1.getClassName is not a function 实例无法访问静态属性
console.log(Point.getClassName()) // Point class 本身才可以访问
  1. constructor 构造函数

当自定义返回值,则 new 出来的对象 p1 不再是 构造函数的实例

1
(p1 instanceof Point)             // false
  1. constructor 中的属性在构造函数上,外部属性方法则在 原型上
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // 构造函数属性的写法
    class Point {
    z = 0 // 可以直接声明构造函数属性
    }
    // 2.
    class Point {
    z // 也可以不初始化值,构造函数当中再赋值
    constructor (x, y, z) {
    this.x = x
    this.y = y
    this.z = z
    }
    }
  2. static 声明一个静态方法,实例无法访问,class 本身可以
  3. 类只有静态方法,没有静态属性
    1
    2
    3
    4
    5
    class Point {
    static attr = 'staticAttr' // undefined
    }

    Point.attr = 'staticAttr' // 可以这样定义静态属性
  4. 私有方法

    只在方法内部,而不暴露给外部

get | set

  • ES5 set、get
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    var info = {
    _age: 18,
    set age (val) {
    if (val > 18) {
    console.log('older');
    } else {
    console.log('too young too simple');
    }
    },
    get age () {
    console.log('my age ?');
    return this._age
    }
    }

    console.log(info.age); // 18
    info.age = 0 // too young too simple
  • ES6 class set | get
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class Info {
    constructor (age) {
    this._age = age
    }
    set age (newAge) {
    console.log('new age is : ' + newAge);
    this._age = newAge
    }
    get age () {
    return this._age
    }
    }

    const info = new Info(18)
    console.log(info); // Info { _age: 18 }
    info.age = 0 // new age is : 0

创建 class

如同 js 函数创建两种形式:创建变量再赋值函数体、函数声明形式直接创建函数体

1
2
3
4
5
6
7
class C {
constructor () {}
}

const AClass = class {
constructor () {}
}

new.target

  • 用于检测方法或构造函数是否是通过 new 被调用的
  • 通过 new 初始化的 函数 或 构造函数中
  • new.target 返回一个指向构造方法或函数的引用
  • 普通函数 则 返回 undefined
1
2
3
4
5
6
7
8
9
10
11
12
class Point {
constructor () {
console.log(new.target); // [class Point]
}
}
const p = new Point()
// console
// class Point {
// constructor () {
// console.log(new.target);
// }
// }

super

作为函数使用

  1. 代表父类的构造函数 constructor
  2. 在使用 extends 继承父类的子类构造函数中,**必须调用一次 super()**,之后才能使用 this
    1
    2
    3
    4
    5
    6
    class Child extends Parent {
    constructor (name, age) {
    super(name) // super 之后才能使用 this
    this.age = age
    }
    }

super 在子类的构造函数中作为 方法使用

子类在构造函数 中使用 super(),父类 构造函数中 的 this 则 指向 子类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Parent
class Parent {
constructor () {
this.name = 'parent name'
console.log(this); // Child { name: 'parent name' }
}
print () {
console.log(this.name);
}
}
// Child
class Child extends Parent {
constructor () {
super()
this.name = 'child name'
}
childPrint () {
super.print()
}
}

const c = new Child()
c.childPrint() // child

作为对象

  1. 在 普通方法中 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
    // Parent
    class Parent {
    constructor () {
    this.type = 'parent'
    }
    getName () {
    return this.type
    }
    }
    Parent.getType = function () {
    return 'type parent'
    }
    // Child
    class Child extends Parent {
    getParentName () {
    // 普通方法中 supre 指向 父类原型对象
    console.log('getParentName: ' + super.getName()) // getParentName: parent
    }
    getParentType () {
    console.log('getParentName: ' + super.getType()) // error
    }
    }

    const c = new Child()
    c.getParentName()
    c.getParentType() // error super 指向父类的原型对象 而不是 父类本身
  2. 在静态方法中,指向父类
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // Parent
    class Parent {
    constructor () {}
    }
    Parent.getType = function () {
    return 'type parent'
    }
    // Child
    class Child extends Parent {
    // static
    static __getParentType () {
    // 静态方法 指向 父类
    console.log('getParentName: ' + super.getType()) // getParentName: parent
    }
    }
    Child.__getParentType() // getParentName: type parent

ES6 class 和 ES5 构造函数实现 继承 的差异

  1. ES5 先创建子构造函数的 this ,再将 父构造函数的属性方法添加到 this
  2. ES6 class 则是先从父类取到实例对象 this,再调用 super() 之后,再将属性和方法添加到 this
-------------本文结束感谢您的阅读-------------