前端基础重点回顾3:原型链、面向对象、继承
创建对象的几种方法
- 字面量创建对象
1
var o1 = { name: 'o1' }
- 使用Object构造函数创建对象
1
var o2 = new Object({ name: 'o2' })
- 使用显式构造函数创建
1
2var Obj = function (name) { this.name = name }
var o3 = new Obj('o3') - 是用Object.create 创建一个指定原型的对象
1
2var proto = { name: 'o4' }
var o4 = Object.create(proto)
原型链
原型链描述
1.从一个实例对象向上找构造这个实例相关联的对象,
2.再从从这个相关联的对象继续向上找创建这个对象相关联的对象,
3.以此类推一直到Object.prototype (null)终止。
原型链通过什么连接和寻找
通过构造函数prototype 和 实例对象的proto 进行寻找
原型对象prototype 有什么特点
构造函数的prototype 由此构造函数创建的多个实例共同使用的对象
instanceof的原理
- 判断实例对象:proto 和构造函数:prototype 两者的引用是否是同一个原型的引用地址(比如Object.prototype )
- 在原型链上的构造函数都会返回true
面向对象
类与实例
1 | var P = function (name) { |
new 操作符使用
1 | // 使用new 操作符直接创建实例 |
new 操作符做了什么
- 创建一个空对象,它继承自构造函数Person.prototype
- 构造函数Person被执行,执行时相应的参数会被传入,同时上下文this会被指定为这个新实例
- 如果构造函数Person返回了一个对象,那么这个对象会取代整个new 出来的结果,如果构造函数没有返回对象,那么new 出来的结果为创建的对象
1 | var new = function(func) { |
继承有几种方式
- 借助构造函数实现继承
1
2
3
4
5
6
7
8
9function Parent () {
this.name = 'parent'
}
Parent.prototype.fn = function () {}
function Child () {
Parent.call(this)
this.type = 'child'
}
缺点: Parent 的原型对象prototype 无法继承 - 借助原型链实现继承
1
2
3
4
5
6
7
8
9
10
11
12
13
14function Parent () {
this.name = 'parent'
this.arr = [1,2,3]
}
function Child () {
this.type = 'child'
}
Child.prototype = new Parent()
优点: 解决了Parent 原型对象的继承
缺点: 由Child 创建的多个实例对象共享父类的引用类型
var c1 = new Child()
var c2 = new Child()
c1.arr.push(4)
c2.arr // [1, 2, 3, 4] - 前两种的组合方式
1
2
3
4
5
6
7
8
9
10
11function Parent () {
this.name = 'parent'
this.arr = [1, 2, 3, 4]
}
function Child () {
Parent.call(this)
this.type = 'child'
}
Child.prototype = new Parent()
优点: 不仅实现了父类prototype 的继承,也通过Parent.call(this) 创建了各实例独自的arr 复杂类型
缺点: 不够优雅,可以优化 - 组合方式优化1
1
2
3
4
5
6
7
8
9
10
11function Parent () {
this.name = 'parent'
this.arr = [1, 2, 3]
}
function Child () {
Parent.call(this)
this.type = 'child'
}
Child.prototype = Parent.prototype
优点: Child不仅继承了Parent 的prototype,而且实现优雅
缺点: Child 创建的实例constructor 指向是Parent, 而且修改了Parent.prototype 会同时改变Child.prototype 和由Child 创建实例的__proto__ - 组合方式优化2
1
2
3
4
5
6
7
8
9
10
11function Parent () {
this.name = 'parent'
this.arr = [1, 2, 3]
}
function Child () {
Parent.call(this)
this.type = 'child'
}
Child.prototype = Object.create(Parent.prototype) // 创建一个纯净的对象
Child.prototype.constructor = Child // 把Child 原型的constructor 指向自己
优点: 不仅完成了继承,同时把Child.prototype.constructor 指向自己,使得每个实例的__proto__.constructor 都指向Child构造函数,更规范。使用Object.create(proto) 方法创建了一个原型对象为Parent.prototype 但是又和Parent.prototype 彻底分离的纯净对象,与Child.prototype 两者互不影响。