# ES6中的类
WARNING
ES5和ES6实现创建实例
- constructor 方法
- 类的实例
- 取值函数(get)和存值函数(set)
- class 表达式
- 静态方法
- 实例属性其他写法
- 实现私有方法
类的继承
Object.getPrototypeOfsuper- 作为函数
- 作为对象
- 类的
prototype属性和__proto__属性
ES5 中实现类
function Point (x, y) {
this.x = x
this.y = y
}
Point.prototype.getPosition = function () {
return `${this.x}-${this.y}`
}
let p1 = new Point(2, 3)
console.log(p1.getPosition())
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
ES6中实现类
class Point2 {
constructor(x, y) {
this.x = x
this.y = y
}
getPosition() {
return `${this.x}-${this.y}`
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
constructor 函数的默认返回值就是 this
class Point2 {
constructor(x, y) {
this.x = x
this.y = y
// 自定义返回对象
return { a: 'a' }
}
getPosition() {
return `${this.x}-${this.y}`
}
}
let p2 = new Point2(1, 3)
console.log(p2 instanceof Point2) // false
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
类的实例,使用 new 调用
console.log(p2.hasOwnProperty('x')) // true
console.log(p2.hasOwnProperty('getPosition')) // false
console.log(p2.__proto__.hasOwnProperty('getPosition')) // true
1
2
3
2
3
get 和 set
对象中的取值和存值
let info = {
_age: 18,
set age(val) {
if (val > 18) {
console.log('大于18')
} else {
console.log('小于18')
}
},
get age () {
console.log('几岁了')
return this._age
}
}
console.log(info.age)
info.age = 20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
类中的取值和存值
class Infos {
constructor(age) {
this._age = age
}
set age (val) {
console.log('设置的新值', val)
this._age = val
}
get age () {
console.log('获取值---')
return this._age
}
}
let infos = new Infos(19)
infos.age = 18
console.log(infos.age)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
静态方法 static , 是类上的方法,不是实例上的
class Point3 {
constructor(x, y) {
this.x = x
this.y = y
}
static getClassName () {
return Point3.name
}
}
let p3 = new Point3(1, 2)
console.log(Point3.getClassName())
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
实例属性的其他写法
class Point4 {
z = 0
}
let p4 = new Point4()
console.log(p4.z)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
TIP
类只有静态方法,没有静态属性
class Point5 {
constructor() {
this.x = 1
}
}
// 变相实现静态属性
Point5.y = 2
let p5 = new Point5()
console.log(p5.x)
console.log(p5.y)
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
私有方法和私有属性,在内部使用,不希望暴露给使用者。
在 js 中使用两种方式来实现私有属性和方法,默认命名规范 和 Symbol
// 模块导出这个,外界就拿不到
let fun1 = Symbol('func1')
class Point6 {
// 默认规范
_func () {}
static [fun1] () {
// 使用 symbol 变相实现
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
new.target 返回整个构造函数
class Point6 {
constructor() {
console.log(new.target)
}
}
let p6 = new Point6()
1
2
3
4
5
6
2
3
4
5
6
# 类的继承
function Food () {
this.type = 'food'
}
Food.prototype.getType = function () {
return this.type
}
function Vegetables (name) {
this.name = name
}
// 最不友好的继承
// 既继承了属性,有继承了方法
// 期望是属性和方法分开继承
Vegetables.prototype = new Food()
let tomato = new Vegetables('tomato')
console.log(tomato.getType())
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Parent {
constructor(name) {
this.name = name
}
getName () {
return this.name
}
// 静态方法也会被继承
static getNames () {
return this.name
}
}
class Child extends Parent {
constructor(name, age) {
// 继承父类的属性
super(name);
this.age = age
}
}
let c = new Child('xiaoyu', 18)
console.log(c) // Child {name: 'xiaoyu', age: 18}
console.log(c instanceof Child) // true
console.log(c instanceof Parent) // true
console.log(Child.getNames()) // Child
// `Object.getPrototypeOf` 获取父类
console.log(Object.getPrototypeOf(Child) === Parent)
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
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
super 函数
作为函数使用,代表父类函数的constructor
作为对象使用,在普通方法中,指向的是父类的原型对象。在静态方法中,指向的是父类
class Parent2 {
constructor() {
this.type = 'parent'
}
getName () {
return this.type
}
}
Parent2.getTypes = () => {
return '父类的静态方法'
}
class Child2 extends Parent2 {
constructor() {
super();
// 此处指向的父类的原型对象
console.log('调用父类原型上的方法--1', super.getName()) // parent
}
getParentName () {
// 此处指向的父类的原型对象
console.log('调用父类原型上的方法--2', super.getName())
}
getParentType () {
console.log('静态方法--1', super.getTypes) // undefined
}
static getParentType2 () {
console.log('静态方法--2', super.getTypes())
}
}
let c2 = new Child2()
c2.getParentName()
c2.getParentType()
Child2.getParentType2()
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
35
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
35
class Parent3 {
constructor() {
this.name = '我是父类name'
}
print () {
console.log(this.name)
}
}
class Child3 extends Parent3 {
constructor() {
super();
this.name = '我是子类name'
}
childPrint () {
// super 指向的是父类的原型对象
super.print()
}
}
let c3 = new Child3()
c3.childPrint() // 我是子类name
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
prototype 和 __proto__
每一个对象都有 __proto__ 属性,指向的是,对应的构造函数的 prototype
let obj2 = new Object()
console.log(obj2.__proto__ === Object.prototype) // true
1
2
2
子类的 __proto__ 指向父类本身
子类的 prototype 属性的 __proto__ 指向父类的 prototype
实例的 __proto__ 属性的 __proto__ 指向父类实例的 __proto__
console.log(Child3.prototype.__proto__ === Parent3.prototype, '原型-a') // true
console.log(Child3.__proto__ === Parent3) // true
console.log(c3.__proto__.__proto__ === Parent3.prototype) // true
1
2
3
2
3
