构造函数
em....,这章主要讲关于 面向对象、原型、原型链、继承。
面向对象
面向对象基本特征:封装、继承、多态,在es6之前没有 class(类),js是通过构造函数模拟的面向对象。
原型
原型(prototype)是一个简单的对象,主要用于实现对象的属性继承。 每个js对象都包含一个__proto__
属性指向该对象原型。
原型链
原型链是由原型对象组成,每个对象都有__proto__
属性,指向了创建该对象的构造函数的原型, __proto__
将对象连接起来组成了原型链。是一个用来实现继承和共享属性的有限的对象链。
- 属性查找机制:当查找对象的属性时,如果实例对象自身不存在该属性,则沿着原型链往上一级查找,找到时则输出,不存在时,则继续沿着原型链往上一级查找,直至最顶级的原型对象
Object.prototype
,如还是没找到,则输出undefined
。 - 属性修改机制:只会修改实例对象本身的属性,如果不存在,则进行添加该属性,如果需要修改原型的属性时,则可以用:
b.prototype.x = 2
;但是这样会造成所有继承于该对象的实例的属性发生改变。
构造函数
可以通过new 运算符新建一个对象的函数。
JavaScript 构造函数命名规范 驼峰式命名
实例
通过构造函数和 new 创建出来的对象,便是实例。
实例通过 __proto__
指向原型,通过 constructor 指向构造函数
构造函数 - 原型 - 实例示例图
new运算符
- 新生成一个对象
- 链接到构造函数的原型:
obj.__proto__ = Con.prototype
- 执行构造函数,并绑定this到新建对象上
- 返回新建对象(如果构造函数自己有return,且返回值类型为Function|Object时,则返回该值)
原理:
function myNew(Con, ...args) {
if (typeof Con !== 'object' && typeof Con !== 'function' || !('constructor' in Con)) {
throw new TypeError(`${Con} is not a constructor`)
}
const obj = Object.create(Con.prototype)
const result = Con.call(obj, ...args)
if (typeof result === 'object' && result !== null || typeof result === 'function') {
return result
}
return obj
}
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
继承
es5构造函数继承
function Person(name) {
this.name = name
}
Person.prototype.play = function() {
console.log(this.name, 'play')
}
// 继承
function Student(name, age) {
Person.call(this, name)
this.age = age
}
Student.prototype = Object.create(Person.prototype)
Student.prototype.constructor = Student
Student.prototype.say = function() {
console.log(this.name, this.age, 'say')
}
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
es6 class 语法糖
class Person(name) {
constructor(name) {
this.name = name
}
play() {
console.log(this.name, 'play')
}
}
class Student extends Person {
constructor(name, age) {
super(name)
this.age = age
}
say() {
console.log(this.name, this.age, 'say')
}
}
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
静态方法
/**
* 静态方法|属性 不需要实例化 直接调用
* Person.play() Person.name
*/
// es6
class Person {
static name = 'person'
static play() {
console.log(Person.name)
}
}
// es5
function Person() {}
Person.name = 'person'
Person.play = function() {
console.log(Person.name)
}
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