# ES6中的类

WARNING

  • ES5和ES6实现创建实例

    • constructor 方法
    • 类的实例
    • 取值函数(get)和存值函数(set)
    • class 表达式
    • 静态方法
    • 实例属性其他写法
    • 实现私有方法
  • 类的继承

    • Object.getPrototypeOf
    • super
      • 作为函数
      • 作为对象
    • 类的 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

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

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

类的实例,使用 new 调用

console.log(p2.hasOwnProperty('x')) // true
console.log(p2.hasOwnProperty('getPosition')) // false
console.log(p2.__proto__.hasOwnProperty('getPosition')) // true
1
2
3

getset

对象中的取值和存值

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

类中的取值和存值

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

静态方法 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

实例属性的其他写法


class Point4 {
	z = 0
}

let p4 = new Point4()
console.log(p4.z)

1
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

私有方法和私有属性,在内部使用,不希望暴露给使用者。

在 js 中使用两种方式来实现私有属性和方法,默认命名规范Symbol

// 模块导出这个,外界就拿不到
let fun1 = Symbol('func1')
class Point6 {
	// 默认规范
	_func () {}
	static [fun1] () {
		// 使用 symbol 变相实现
	}
}

1
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

# 类的继承

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
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

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
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

prototype__proto__

每一个对象都有 __proto__ 属性,指向的是,对应的构造函数的 prototype

let obj2 = new Object()
console.log(obj2.__proto__ === Object.prototype) // true
1
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

静态图片