这是我参与8月更文挑战的第18天,活动详情查看:8月更文挑战
温故知新,还记得这张图么?
上篇我们讲了原型对象的使用(传送门),今天继续下一个知识点,也就是构造函数的三大特点之一:继承。
是什么?有什么用? 我们一步步的了解,开始今天的学习啦~
一、面向对象-继承
1. 概念解析
三个类
- 超类型
- 父类型
- 子类型
举例:
类: 动物 狗类 哈士奇
对于狗类来说
动物是它的父类型,而哈士奇类是它的子类型
对于哈士奇类来说
狗类是它的父类型,动物类是它的超类型.
复制代码
继承就是让子类拥有父类的资源
2. 概念解析继承的方式
- 01-原型链继承
- 02-借用构造函数继承
- 03-组合继承
- 04-原型式继承
- 05-寄生式继承
- 06-寄生式组合继承
- 07-拷贝属性继承
3. 继承的意义
- 减少代码冗余
- 方便统一操作
- 弊端 —- 耦合性比较强
二、继承-原型链继承-原型链实战
- 每个函数都能构建出一个对象, 这个对象内部有个属性指向着这个函数的原型对象
- 原型对象本质也是一个对象,也是由另外一个构造函数构造出来, 也指向那个构造函数的原型对象
以上,形成一个链式的结构
,就称为是原型链
测试代码
console.log(arr.constructor.name); // Array
console.log(arr.__proto__.constructor.name); // Array
console.log(Array.__proto__.constructor.name); // Function
console.log(Function.__proto__.constructor.name); // Function
console.log(Function.prototype.__proto__.constructor.name); // Object
console.log(Object.prototype.__proto__); // null
console.log(Object.__proto__.constructor.name); // Function
console.log(Array.prototype.__proto__.constructor.name); // Object
复制代码
图解
三、继承-原型链继承-原型链检索规则
- 对象.属性的方法去访问属性的时候,先查找有没有对应的实例属性,如果有那么就直接使用
- 如果没有,那么就去该对象的原型对象上面去找,如果有那么就直接使用
- 如果没有,那么就接着查找原型对象的原型对象,如果有,那么就直接使用,
- 如果没有,那么就继续上面的搜索过程
- 直到搜索到Object.prototype为止,如果还是没有找到就返回undefined或者是报错
注意:
- 原型链搜索的路径越长,查询属性所花费的时间就越多
- 原则:就近原型
四、继承-原型链继承-0
说明:从这开始,每一个大标题都会有一个问题,然后在下一个标题内容解决掉又继续抛出问题。 以此类推。
未继承效果: stu对象, 访问不到Person里面的任何内容
<script>
/**
* 构造函数Person
* @constructor
*/
function Person() {
this.name = 'Jack';
this.lore = ['html', 'css'];
}
Person.prototype.run = function () {
console.log('跑');
};
/**
* 构造函数Student
* @constructor
*/
function Student() {
this.num = 'Tom';
}
var stu = new Student();
console.log(stu); // Student {num: "Tom"}
console.log(stu.num); // Tom
console.log(stu.name); // undefined
console.log(stu.lore); // undefined
stu.run(); // 报错 Uncaught TypeError: stu.run is not a function
</script>
复制代码
图解
问题:子对象无法访问到父类的任何东西?
五、继承-原型链继承-1
这里我们都知道查找规则是什么样的了,首先自己没有, 就到原型对象上面查找…
所以我们来解决上面的问题:子对象无法访问到父类的任何东西?
所以我们就考虑到两点:
- 要不考虑给添加到自己身上
- 只能自己有
- 以后的其他对象, 就没了
- 要不考虑给添加到原型身上
关于两者之间的区别大家可以去尝试尝试,我们就直接给出我这边的解决方案了。
解决方案:修改原型指向比较方便
<script>
/**
* 构造函数Person
* @constructor
*/
function Person() {
this.name = 'Jack';
this.lore = ['html', 'css'];
}
Person.prototype.run = function () {
console.log('跑');
};
/**
* 构造函数Student
* @constructor
*/
function Student() {
this.num = 'Tom';
}
// 让Student的原型对象--->Person的原型对象
Student.prototype = Person.prototype;
var stu = new Student();
console.log(stu); // Student {num: "Tom"}
console.log(stu.num); // Tom
stu.run(); // 跑
</script>
复制代码
图解
到了这里,我们会产生一个问题: 无法访问到父类的对象属性? 大家可以思考思考,我们下期来进行解答。
所以明天我们继续,解答一下上面的那个问题,敬请期待!
八、结语
码字画图不易,如果觉得对你有帮助,觉得还不错的话,欢迎点赞收藏~
当然由于是个人整理,难免会出现纰漏,欢迎留言反馈。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END