一.JavaScript 高级
1.任务目标
- JavaScript 继承
2 .重点
- JavaScript 继承
3.难点
- JavaScript 继承
二.核心内容
JavaScript 继承
什么是继承
js中的继承就是获取存在对象已有属性和方法的一种方式.
面向对象语言的三大特征:
继承、封装、多态
JavaScript不是真正的面向对象,它只是基于面向对象,所以会有自己独特的地方。
那么JavaScript的继承是如何实现的?
答案是 原型链!
其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。
JavaScript中有6种经典的实现继承方法
1.原型链继承
2.借用构造函数
3.组合继承
4.原型式继承
5.寄生式继承
6.寄生组合式继承
原型链继承
-
方法
定义父类型构造函数
给父类型的原型添加方法
定义子类型的构造函数
创建父类型的对象赋值给子类型的原型
将子类型原型的构造属性设置为子类型
给子类型原型添加方法
创建子类型的对象: 可以调用父类型的方法 -
关键
子类型的原型为父类型的一个实例对象<!-- 方式1: 原型链继承 1. 套路 1. 定义父类型构造函数 2. 给父类型的原型添加方法 3. 定义子类型的构造函数 4. 创建父类型的对象赋值给子类型的原型 5. 将子类型原型的构造属性设置为子类型 6. 给子类型原型添加方法 7. 创建子类型的对象: 可以调用父类型的方法 2. 关键 1. 子类型的原型为父类型的一个实例对象 --> <script type="text/javascript"> //父类型 function Supper() { this.supProp = 'Supper property' } Supper.prototype.showSupperProp = function () { console.log(this.supProp) } //子类型 function Sub() { this.subProp = 'Sub property' } // 子类型的原型为父类型的一个实例对象 Sub.prototype = new Supper() // 让子类型的原型的constructor指向子类型 Sub.prototype.constructor = Sub Sub.prototype.showSubProp = function () { console.log(this.subProp) } var sub = new Sub() sub.showSupperProp() // sub.toString() sub.showSubProp() console.log(sub) // Sub </script>
借用构造函数继承
1.方法:
定义父类型构造函数
定义子类型构造函数
在子类型构造函数中调用父类型构造
2.关键:
在子类型构造函数中通用call()调用父类型构造函数
<!--
方式2: 借用构造函数继承(假的)
1. 套路:
1. 定义父类型构造函数
2. 定义子类型构造函数
3. 在子类型构造函数中调用父类型构造
2. 关键:
1. 在子类型构造函数中通用call()调用父类型构造函数
-->
<script type="text/javascript">
function Person(name, age) {
this.name = name
this.age = age
}
function Student(name, age, price) {
Person.call(this, name, age) // 相当于: this.Person(name, age)
/*this.name = name
this.age = age*/
this.price = price
}
var s = new Student('Tom', 20, 14000)
console.log(s.name, s.age, s.price)
</script>
组合继承
方法: 原型链+借用构造函数的组合继承
利用原型链实现对父类型对象的方法继承
利用super()借用父类型构建函数初始化相同属性
<!--
方式3: 原型链+借用构造函数的组合继承
1. 利用原型链实现对父类型对象的方法继承
2. 利用super()借用父类型构建函数初始化相同属性
-->
<script type="text/javascript">
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.setName = function (name) {
this.name = name
}
function Student(name, age, price) {
Person.call(this, name, age) // 为了得到属性
this.price = price
}
Student.prototype = new Person() // 为了能看到父类型的方法
Student.prototype.constructor = Student //修正constructor属性
Student.prototype.setPrice = function (price) {
this.price = price
}
var s = new Student('Tom', 24, 15000)
s.setName('Bob')
s.setPrice(16000)
console.log(s.name, s.age, s.price)
</script>
原型式继承
这是另一种继承,没有严格意义上的构造函数
方法:
借助原型可以基于已有的对象创建新对象,同时还不必要创建自定义类型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a0EmU4xO-1676294246429)(继承.assets\image-20220808193422733.png)]
寄生式继承
寄生式继承是与原型式继承紧密相关的一种思路,与寄生式构造函数和工厂模式类似;
即创建一个仅用于封装继承过程的函数;
该函数在内部以某种方式来增强对象;
最后再像真地是它做了所有工作一样返回对象;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lxfFNH49-1676294246430)(继承.assets\image-20220808193514768.png)]
寄生组合式继承
通过借用函数来继承属性,通过原型链的混成形式来继承方法
通过寄生方式,砍掉父类的实例属性
在调用两次父类的构造的时候
不会初始化两次实例方法/属性
避免的组合继承的缺点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T1desH75-1676294246430)(继承.assets\image-20220808193616681.png)]
三、总结
- 继承
原型链
借用构造函数
组合继承
原型式继承
寄生式继承
承
通过借用函数来继承属性,通过原型链的混成形式来继承方法
通过寄生方式,砍掉父类的实例属性
在调用两次父类的构造的时候
不会初始化两次实例方法/属性
避免的组合继承的缺点
[外链图片转存中…(img-T1desH75-1676294246430)]
三、总结
- 继承
原型链
借用构造函数
组合继承
原型式继承
寄生式继承
寄生组合式继承