第二十五章 继承
创始人
2024-03-27 14:16:59
0

一、继承

1、含义:继承就是获取存在对象已有属性和方法的一种方式

2、继承关系出现在构造函数和构造函数之间

3、 构造函数A 继承自 构造函数B

  • 子类:构造函数A
  • 父类:构造函数B

二、继承分类

1、原型继承

2、借用构造函数继承

3、组合继承

4、类(ES6)的继承

5、拷贝继承....

三、原型继承

1、核心: 让子类的原型指向父类的实例,即把父类的实例赋值给子类的原型

2、优点: 父类构造函数体内的属性和原型上的方法都可以实现继承

3、缺点:

  • 继承下来的属性不在自己身上, 在自己的原型上
  • 一个构造函数的实例, 需要在两个地方传递参数
  • 所有子类的实例, 继承下来的属性是一样的

四、借用构造函数继承

1、核心:把父类构造函数当做普通函数调用, 并且改变其 this 指向

2、优点

  • 把父类构造函数当做普通函数调用, 并且改变其 this 指向
  • 子类的所有参数在一个地方传递
  • 子类的所有实例都可以给继承下来的属性赋不一样的值

3、缺点:父类的原型上的方法没有继承下来

    // 父类function Person(name, age) {this.name = namethis.age = age}Person.prototype.play = function() {console.log('玩游戏')}// 子类function Student(classRoom, name, age) {this.classRoom = classRoom// 实现继承Person.call(this, name, age)}const s = new Student(2114, 'Jack', 18)console.log(s)const s2 = new Student(2115, 'Rose', 20)console.log(s2)

五、组合继承

1、核心:把原型继承和借用构造函数继承放在一起使用

2、优点

  • 既可以继承属性也可以继承方法
  • 可以传递不同的参数
  • 可以在同一个地方传递参数

3、缺点:子类的原型上多了一套属性,无法去除,若实例化的过程中没有赋值,结果是undefined

4、这样的继承方式在我们es6出现之前,我们也称之为完美继承

    // 父类function Person(name, age) {this.name = namethis.age = age}Person.prototype.play = function() {console.log('玩游戏')}// 子类function Student(classRoom, name, age) {this.classRoom = classRoom// 借用继承// 目的: 把属性继承在自己身上Person.call(this, name, age)}// 原型继承// 目的: 继承父类原型上的方法Student.prototype = new Person()// 创建子类的实例const s = new Student(2114, 'Rose', 20)console.log(s)

六、ES6继承

1、类的继承是ES6中提出的一种继承方式

2、实现步骤
第一步:

  • 书写子类的时候, 加上 extends 关键字  
  • 语法:class 子类 extends 父类 {}
  • 目的:目的: 继承父类原型上的方法

第二步:

  • 在子类的 constructor 内书写 super(实参)
  • 目的: 继承父类的属性

注意:(1)必须要书写 super 和 extends

(2)在子类的 constructor 内 super 必须写在 this.xxx 的前面(最前面)

(3)父类可以是构造函数,但是子类不能的构造函数因为extends和super关键字就是给类设计的

    // 父类class Person {constructor(name, age) {this.name = namethis.age = age}play() {console.log('玩游戏')}}// 父类// function Person(name, age) {//   this.name = name//   this.age = age// }// Person.prototype.play = function () { console.log('玩游戏') }// 子类class Student extends Person {constructor(classRoom, name, age) {super(name, age)this.classRoom = classRoom}study() {console.log('学习')}}const s = new Student(2114, 'Jack', 18)console.log(s)class Teacher extends Person {constructor(gender, name, age) {super(name, age)this.gender = gender}}const t = new Teacher('男', 'Jack', 20)console.log(t)

七、拷贝继承

1、核心:利用 for in 循环遍历对象,把所有的内容复制一份放在子类的原型上

2、in

  • in是一个关键字
  • 作用:就是检测这个对象中有没有这个键
  • 返回值:有返回true
  • 没有返回false

注意:in这个关键字不光能检测自己身上的,也可以检测原型对象上的;

延伸:hasOwnPrototype() :也是用来检测这个键是不是在对象上的

=>语法:对象.hasOwnPrototype('对象名')

=>返回值也是布尔值

注意:这个方法只能检测自身的,不能检测原型对象上的

        function Person(name){this.name = name          }const p = new Person('aa')// 使用in检测对象p中是否有这个键名 nameconsole.log('name' in p); //trueconsole.log('age' in p); //false// 在原型上添加一个属性Person.prototype.age = 18// 检测原型对象上console.log('age' in p);//true// console.log(p.hasOwnPrototype('name')); //true// console.log(p.hasOwnPrototype('age')); //false

3、拷贝继承

        function Person(name,age){this.name = name          this.age = age          }Person.prototype.sayHi = function(){console.log(111);}// 子类继承我们的父类function Student (classdom,name,age){this.classdom = classdom// 这里实现我们的继承// 首先实例化我们的父类对象let p = new Person(name,age)// 使用for in循环for(let k in p){// 把我们对象上的键和值赋给子类的原型对象Student.prototype[k] = p[k]}}// 实例化一个子类let s = new Student(2217,'aaa',22)console.log(s);

4、 原生的深浅拷贝
                => 深浅拷贝指的是一种复制对象或者数组的行为
                => 也就是把一个对象或者数组中的数据完完整整的复制一份放到另一个数组或者对象中
                => 并且相互之间没有联系,修改一个另一个不受影响
                => 说道深浅拷贝这个我们不考虑基本数据类型 
                => 因为基本数据类型没有引用地址一说 
                => 说到复制这个事儿 有三个级别
                    -> 赋值
                    -> 浅拷贝
                    -> 深拷贝
            赋值
                => 就是把一个变量存储的内容复制一份给另一个变量
                => 基本数据类型赋值以后两个变量之间没有关系
                => 修改任何一个的值都不会影响另一个
                
                => 复杂数据类型赋值以后,两个变量操作一个空间
                => 修改一个的值另一个也会跟着改变

        // 赋值// 基本数据类型let num = 100let num1 = numconsole.log(num, num1);num1 = 200console.log(num, num1);// 复杂数据类型let o1 = { name: 'Jack', age: 25 }let o2 = o1console.log(o1, o2);o2.name = 'Rose'console.log(o1, o2);

            浅拷贝
                => 说到浅拷贝就不考虑基本数据类型了
                => 就是按照原先的数据类型创建一个新的一样的数据类型
                => 把原始数据中的每一个数据依次赋值到新的数据类型中
                => 通过分析我们发现浅拷贝只能拷贝一层 
                => 并且是简单数据类型 如果有第二层甚至多层就不能实现完完整整的复制

                =>我们修改其中一个值的时候,另一个依旧会受到影响,所以不能多层拷贝

        // 浅拷贝const o1 = {name: 'Jack',age: 25,color: {red: '红色',blue: '蓝色'}}// // 实现拷贝// // 首先创建一个新的数据const o2 = {}// 遍历循环原始数据类型for (let k in o1) {// 接下来就是把原始数据类型中的数据赋值到新创建的数据类型中// 如果这个时候元素对象中还复杂数据类型// 同样是赋值 依然不能实现完完整整的复制o2[k] = o1[k]}console.log(o1, o2);// 修改o1中的值o1.color.red = '红颜色'console.log(o1, o2);

            深拷贝

第一种:递归

               =>依旧是不考虑我们的基本数据类型
                => 就是要百分百的拷贝一份原始数据
                => 修改任何里面的数据都不会影响另一个里面的数据
                => 不管层级有多深 都能完整的复制过来 两个之间没有关系
                => 这就要通过深拷贝
                => 深拷贝的核心:递归

                实现步骤:

        // 准备数据const o1 = {name: 'Jack',age: 18,info: {height: 180,weight: 180,desc: {message: '今天天气很好'}},address: {city: '北京'},hobby: ['吃饭', '睡觉']}// 准备一个空对象const o2 = {}// 要实现深拷贝 我们就准备一个函数function deepCopy(o2, o1) {// 首先我们还是要通过循环遍历的方式拿到原始数据类型中的数据for (let k in o1) {// 因为我们不知道里面都有什么数据所以我们要先判断if (Object.prototype.toString.call(o1[k]) === '[object Object]') {// 代码能进入到这里说明是一个对象o2[k] = {}// 再次进行拷贝 这个过程和我们刚做的是不是一样// 那我就直接调用我们的deepCopy函数就好deepCopy(o2[k], o1[k])} else if (Object.prototype.toString.call(o1[k]) === '[object Array]') {// 代码能执行到这里说明是一个数组o2[k] = []// 继续执行我们的拷贝函数deepCopy(o2[k], o1[k])} else {o2[k] = o1[k]}}}// 使用deepCopy(o2, o1)// console.log(o1, o2);o1.info.height = 300console.log(o1, o2);

第二种:JSON

        =>把你要拷贝的数据转成 JSON格式字符串

        // 这是我们要拷贝的数据const o1 = {name: 'Jack',age: 18,info: {height: 180,weight: 180,desc: {message: '今天天气很好'}},address: {city: '北京'},hobby: ['吃饭', '睡觉',[10, 20]]}// 就是把你要拷贝的数据转成 JSON格式字符串let jsonO1 = JSON.stringify(o1)console.log(jsonO1);// 之后在转换回来let o2 = JSON.parse(jsonO1)console.log(o2);// 就是验证我们的拷贝结果了console.log('原始数据(对象) :', o1);console.log('拷贝完毕后的数据(对象) :', o2);

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...