原型
认识原型
在JavaScript中,原型也是一个对象,通过原型可以实现对象的属性继承,JavaScript的对象中都包含了一个” [[Prototype]]”内部属性,这个属性所对应的就是该对象的原型。
“[[Prototype]]”作为对象的内部属性,是不能被直接访问的。所以为了方便查看一个对象的原型,Firefox和Chrome中提供了”__proto__
“这个非标准(不是所有浏览器都支持)的访问器(ECMA引入了标准对象原型访问器”Object.getPrototype(object)”)。
prototype
和 __proto__
- 对于所有的对象,都有
__proto__
属性,这个属性对应该对象的原型 - 对于函数对象,除了
__proto__
属性之外,还有prototype
属性,当一个函数被用作构造函数来创建实例时,该函数的prototype属性值将被作为原型赋值给所有对象实例(也就是设置实例的__proto__
属性)
constructor
从上面的图我们可以注意到,每个原型对象还有一个属性:constructor
,constructor是对象才有的属性。原型对象的constructor属性指向的是我们自己定义的构造函数,或者是内置的构造函数。
构造函数
- 构造函数是专门用来创建对象的函数
- 一个构造函数我们也可以称为一个类
- 通过一个构造函数创建的对象,我们称该对象时这个构造函数的实例
- 通过同一个构造函数创建的对象,我们称为一类对象
- 构造函数就是一个普通的函数,只是他的调用方式不同
- 如果直接调用,它就是一个普通函数
- 如果使用
new
来调用,则它就是一个构造函数
1 | function Person(fName,lName,age){ |
为了避免创建对象时方法的重复创建导致浪费内存,可以将方法放入构造函数的原型中
1 | function Person(fName,lName,age){ |
原型链
什么是原型链
因为每个对象和原型都有原型,对象的原型指向对象的父,而父的原型又指向父的父,这种原型层层连接起来的就构成了原型链。
属性查找
当查找一个对象的属性时,JavaScript 会向上遍历原型链,直到找到给定名称的属性为止,到查找到达原型链的顶部,如果仍然没有找到指定的属性,就会返回 undefined。比如:
1 | function Person(name, age){ |
hasOwnProperty()
- 这个方法可以用来检查对象自身是否含有某个属性
- 不会向上查找原型链
- 语法:
对象.hasOwnProperty(“属性名”)
原型和原型链的总结
- 原型: 可以理解为是对象的
__proto__
属性或者是函数的prototype
属性所指向的对象 - 原型对象: 构造函数的
prototype
属性所指的对象 - 原型链: 对象的
__proto__
访问器属性,或者[Prototype]内部属性指向的逐级向上最终为null的链式路径,大概的意思就是object.__proto__
(父级).__proto__
(祖父级).null(最后的__proto__
)
继承
原型链继承
1 | function User() {} |
组合继承
使用call()
使用父类构造函数初始属性。
1 | function User(name, age) { |
多态
1 | function User() {} |
使用mixin实现多继承
mixin 可以理解为一个混合功能
1 | function extend(sub, sup) { |
内部继承和super
关键字
super
指向的是当前对象的原型对象。
1 | function extend(sub, sup) { |
GitHub Issues