# 七.类
# 1. class
# 2. get 和 set
# 3. static
# 4. extends
在 es5 中没有类的概念 构造函数
es6 class
类的继承 三种属性 公有属性(proto) 私有属性 静态方法(静态属性)
function Parent() {
//构造函数中的this 通过new调用的那么this指代的是实列
this.name = "parent"
}
Parent.prototype.eat = function () {
console.log("eat")
}
let parent = new Parent()
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
先找私有属性找不到然后找公有属性
parent.__proto__.eat()
Parent.prototype.constructor === Parent
function Child() {
this.age = 9
Parent.call(this)
}
let child = new Child()
console.log(child.name)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 1.继承私有属性
# 2.继承公有属性
Child.prototype.__proto__ = Parent.prototype
Object.setPrototypeOf(Child.prototype, Parent.prototype)
//只继承公有
Child.prototype = Object.create(Parent.prototype, {
constructor: { value, Child },
})
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# create 实现原理
首先看一看 defineProperty
let a = {}
a.name = 1
console.log(a.name)
Object.defineProperty(a, "name", {
enumerable: true, //表示这个属性是否可以被枚举出来
configurable: true, //表示这个属性是否可以被删除
// writable: true,//用了这个就不能用get set
get() {
console.log("get")
return 1
},
set() {},
})
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
实现 create
function create(parentPrototype) {
function Fn() {}
Fn.prototype = parentPrototype
let fn = new Fn()
for (let key in props) {
Object.defineProperty(fn, key, {
...props[key],
enumerable: true,
})
}
return fn
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 3.继承公有属性和私有属性
Child.prototype = new Parent()
1
# 类的编译
class Parent {
constructor() {
this.mame = "parent"
return {}
}
static b() {
return 2
}
eat() {
console.log("eat")
}
}
class Child extends Parent {
constructor() {
this.age = 9 //私有属性
}
static a() {
//静态属于类上的方法
return 1
}
smoking() {
//原型上的方法
console.log("somking")
}
}
let child = new Child()
console.log(child.smoking)
console.log(child.a())
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
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
- 1.类只能 new
Child() //运行会报错
1
- 2.类可以继承公有私有和静态方法
- 3.父类的构造函数中返回了一个引用类型会把这个引用类型作为子类的 this
# 类的原理
# 类的调用检测检测实列是不是 new 出来的
function _classCallCheck(instance, constructor) {
if (!(instance instanceof constructor)) {
throw new Error("Class constructor Child cannot be invoked without")
}
}
1
2
3
4
5
2
3
4
5
# 创建类
constructor 是构造函数
protoPropertys 是原型方法的描述
staticPropertys 是静态方法的描述
function definePropertys(target, arr) {
for (let i = 0; i < arr.length; i++) {
Object.defineProperty(target, arr[i].key, {
...arr[i],
configurable: true,
enumerable: true,
writable: true,
})
}
}
function _createClass(constructor, protoPropertys, staticPropertys) {
if (protoPropertys.length > 0) {
definePropertys(constructor.prototype, protoPropertys)
}
if (staticPropertys.length > 0) {
definePropertys(constructor, staticPropertys)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 创建一个类
let Parent = (function () {
//为了方便扩展
function P() {
_classCallCheck(this, P)
}
_createClass(
P,
[
{
key: "eat",
value: function () {
console.log("吃")
},
},
],
[
{
key: "b",
value: function () {
return 2
},
},
]
)
return P
})()
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
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
# 使用
let p = new Parent()
console.log(Parent.b())
1
2
2
# 子类继承父类
function _inherits(subClass, superClass) {
//继承公有属性
subClass.prototype = Object.create(superClass.prototype, {
constructor: { value: subClass },
})
//继承静态方法
Object.setPrototypeOf(subClass, superClass)
}
let Child = (function (Parent) {
//先实现继承父类的公有属性和静态方法
_inherits(C, Parent)
function C() {
_classCallCheck(this, C)
let obj = Parent.call(this)
if (typeof obj === "object") {
return (obj.age = 9)
} else {
return (this.age = 9) //解决了父类返回了一个引用类型的问题
}
}
return C
})(Parent)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
使用
let child = new Child()
console.log(child.b())
1
2
2
# 8.继承
//在es5中没有类的概念 构造函数
//es6 class
//类的继承 三种属性 公有属性(__proto__) 私有属性 静态方法(静态属性)
function Parent() {
//构造函数中的this 通过new调用的那么this指代的是实列
this.name = "parent"
}
Parent.prototype.eat = function () {
console.log("eat")
}
let parent = new Parent()
//先找私有属性找不到然后找公有属性
parent.__proto__.eat()
Parent.prototype.constructor === Parent
function Child() {
this.age = 9
Parent.call(this)
}
let child = new Child()
console.log(child.name)
//1.继承私有属性
//继承公有属性
Child.prototype.__proto__ = Parent.prototype
Object.setPrototypeOf(Child.prototype, Parent.prototype)
//只继承公有
Child.prototype = Object.create(Parent.prototype, {
constructor: { value, Child },
})
//实现原理
function create(parentPrototype) {
function Fn() {}
Fn.prototype = parentPrototype
let fn = new Fn()
for (let key in props) {
Object.defineProperty(fn, key, {
...props[key],
enumerable: true,
})
}
return fn
}
let a = {}
a.name = 1
console.log(a.name)
Object.defineProperty(a, "name", {
enumerable: true, //表示这个属性是否可以被枚举出来
configurable: true, //表示这个属性是否可以被删除
// writable: true,//用了这个就不能用get set
get() {
console.log("get")
return 1
},
set() {},
})
//3.继承公有属性和私有属性
Child.prototype = new 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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# 9.类的编译
//类的编译
class Parent {
constructor() {
this.mame = "parent"
return {}
}
static b() {
return 2
}
eat() {
console.log("eat")
}
}
class Child extends Parent {
constructor() {
this.age = 9 //私有属性
}
static a() {
//静态属于类上的方法
return 1
}
smoking() {
//原型上的方法
console.log("somking")
}
}
let child = new Child()
console.log(child.smoking)
console.log(child.a())
//1.类只能new
Child() //运行会报错
//2.类可以继承公有私有和静态方法
//3.父类的构造函数中返回了一个引用类型会把这个引用类型作为子类的this
//类的原理
//类的调用检测检测实列是不是new出来的
function _classCallCheck(instance, constructor) {
if (!(instance instanceof constructor)) {
throw new Error("Class constructor Child cannot be invoked without")
}
}
//constructor是构造函数
//protoPropertys 是原型方法的描述
//staticPropertys 是静态方法的描述
function definePropertys(target, arr) {
for (let i = 0; i < arr.length; i++) {
Object.defineProperty(target, arr[i].key, {
...arr[i],
configurable: true,
enumerable: true,
writable: true,
})
}
}
function _createClass(constructor, protoPropertys, staticPropertys) {
if (protoPropertys.length > 0) {
definePropertys(constructor.prototype, protoPropertys)
}
if (staticPropertys.length > 0) {
definePropertys(constructor, staticPropertys)
}
}
let Parent = (function () {
//为了方便扩展
function P() {
_classCallCheck(this, P)
}
_createClass(
P,
[
{
key: "eat",
value: function () {
console.log("吃")
},
},
],
[
{
key: "b",
value: function () {
return 2
},
},
]
)
return P
})()
let p = new Parent()
console.log(Parent.b())
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# 10.类的继承
//子类继承父类
function _inherits(subClass, superClass) {
//继承公有属性
subClass.prototype = Object.create(superClass.prototype, {
constructor: { value: subClass },
})
//继承静态方法
Object.setPrototypeOf(subClass, superClass)
}
let Child = (function (Parent) {
//先实现继承父类的公有属性和静态方法
_inherits(C, Parent)
function C() {
_classCallCheck(this, C)
let obj = Parent.call(this)
if (typeof obj === "object") {
return (obj.age = 9)
} else {
return (this.age = 9) //解决了父类返回了一个引用类型的问题
}
}
return C
})(Parent)
let child = new Child()
console.log(child.b())
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25