对于JavaScript继承你到底了解多少

2022-04-15 0 1,103
目录
  • 前言
    • 构造函数,原型对象,实例对象三者之间的关系
  • 原型链继承
    • 借⽤构造函数继承
      • 原型式继承
        • 寄生式继承
          • 组合继承(组合原型链继承和借用构造函数继承)
            • 寄生组合式继承
              • 总结

                前言

                关于继承,你到底了解多少,什么样的继承是最最优的,让我们一起来学习一些关于继承的那些知识点,带你了解他们的实现过程,以及他们的优缺点

                构造函数,原型对象,实例对象三者之间的关系

                先来了解他们的关系有助于对继承更好的理解

                对于JavaScript继承你到底了解多少

                原型链继承

                核⼼:将⽗类实例作为⼦类原型

                代码实现过程:

                function Parent(name){
                    this.name = name || 'xt',
                    this.arr = [1]
                }
                function Son(age){
                    this.age = age
                }
                Parent.prototype.say = function() { //将需要复⽤、共享的⽅法定义在⽗类原型上
                    console.log('hello');
                }
                Son.prototype = new Parent()
                let s1 = new Son(18)
                let s2 = new Son(19)
                console.log(s1.say() === s2.say()); //true
                console.log(s1.name,s1.age); //xt 18
                console.log(s2.name,s2.age); //xt 19
                s1.arr.push(2)
                console.log(s1.arr,s2.arr); // [ 1, 2 ] [ 1, 2 ]
                

                优点:

                实例可继承的属性有:实例的构造函数的属性,父类构造函数属性,父类原型的属性。(新实例不会继承父类实例的属性!)

                缺点:

                • ⼦类实例共享了⽗类构造函数的引⽤属性,⽐如arr属性(原型上的属性是共享的,一个实例修改了原型属性,另一个实例的原型属性也会被修改!)
                • 不能向⽗类构造函数传参

                借⽤构造函数继承

                核心:借⽤⽗类的构造函数来增强⼦类实例,等于是复制⽗类的实例属性给⼦类

                代码实现:

                function Parent(name) {
                    this.name = name;
                    this.arr = [1],
                    this.say = function() { console.log('hello') }
                }
                function Son(name, age) {
                    Parent.call(this, name) // 拷⻉了⽗类的实例属性和⽅法
                    this.age = age
                }
                let s1 = new Son('小谭', 18)
                let s2 = new Son('小明', 19)
                console.log(s1.say === s2.say) //false ⽅法不能复⽤ ⽅法是独⽴,不是共享的
                console.log(s1.name, s1.age); //小谭 18
                console.log(s2.name, s2.age); //小明 19
                s1.arr.push(2)
                console.log(s1.arr, s2.arr); // [ 1, 2 ] [ 1 ]
                

                优点:

                • 只继承了父类构造函数的属性,没有继承父类原型的属性。
                • 可以继承多个构造函数属性(call多个)
                • 在子实例中可向父实例传参。

                缺点:

                • 只能继承父类构造函数的属性。
                • 无法实现构造函数的复用。(每次用每次都要重新调用)
                • 每个新实例都有父类构造函数的副本,臃肿。

                原型式继承

                核心:用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了个可以随意增添属性的实例或对象

                function Parent(name) {
                    this.name = 'xt';
                    this.arr = [1]
                }
                function object(obj){
                    function F(){}
                    F.prototype = obj;
                    return new F();
                  }
                let s1 = new Parent(object)
                s1.name = '小明'
                s1.arr.push(2)
                let s2 = new Parent(object)
                console.log(s1.name,s2.name); // 小明 xt
                console.log(s1.arr, s2.arr); //[ 1, 2 ] [ 1 ]
                

                缺点:

                • 所有实例都会继承原型上的属性,无法传递参数
                • 无法实现复用。(新实例属性都是后面添加的)

                寄生式继承

                核心:在原型式继承的基础上,增强对象,返回构造函数

                function Parent(name) {
                    this.name = 'xt';
                    this.arr = [1]
                }
                function object(obj){
                    function F(){}
                    F.prototype = obj;
                    return new F();
                  }
                let Son = new Parent()
                function addobject(obj){
                    var add = object(obj)
                    add.name = '小白'
                    return add
                }
                var s1 = addobject(Son)
                console.log(s1.name); //小白
                

                缺点:

                • 没用到原型,无法复用。
                • 原型链继承多个实例的引用类型属性指向相同,存在篡改的可能。

                组合继承(组合原型链继承和借用构造函数继承)

                核心:通过调⽤⽗类构造函数,继承⽗类的属性并保留传参的优点;然后通过将⽗类实例作为⼦类原型,实现函数复⽤。

                代码实现:

                function Parent(name) {
                    this.name = name;
                    this.arr = [1]
                }
                Parent.prototype.say = function () { console.log('hello') }
                function Son(name, age) {
                    Parent.call(this, name) // 二次
                    this.age = age
                }
                Parent.prototype = new Son() // 一次
                let s1 = new Son('小谭', 18)
                let s2 = new Son('小明', 19)
                console.log(s1.say === s2.say) // true
                console.log(s1.name, s1.age); //小谭 18
                console.log(s2.name, s2.age); //小明 19
                s1.arr.push(2)
                console.log(s1.arr, s2.arr); // [ 1, 2 ] [ 1 ] 不共享⽗类的引⽤属性,
                

                优点:

                • 保留构造函数的优点:创建⼦类实例,可以向⽗类构造函数传参数。
                • 保留原型链的优点:⽗类的⽅法定义在⽗类的原型对象上,可以实现⽅法复⽤。
                • 不共享⽗类的引⽤属性。⽐如arr属性

                缺点:

                • 由于调⽤了2次⽗类的构造⽅法,会存在⼀份多余的⽗类实例属性

                寄生组合式继承

                核心:结合借用构造函数传递参数和寄生模式实现继承

                function Parent(name){
                    this.name = name || 'xt',
                    this.arr = [1]
                }
                function Son(name,age){
                    Parent.call(this,name) // 核⼼
                    this.age = age
                }
                Parent.prototype.say = function() {  
                    console.log('hello');
                }
                Son.prototype = Object.create(Parent.prototype) // 核心 通过创建中间对象,⼦类原型和⽗类原型,就会隔离开。
                Son.prototype.constructor = Son
                let p1 = new Parent()
                
                let s1 = new Son("小红",18)
                let s2 = new Son("小黑",19)
                console.log(p1.constructor); //[Function: Parent]
                console.log(s1.constructor); // [Function: Son]
                console.log(s1.say() === s2.say()); //true
                console.log(s1.name,s1.age); // 小红 18
                console.log(s2.name,s2.age); //小黑 19
                s1.arr.push(2)
                console.log(s1.arr,s2.arr); // [ 1, 2 ] [ 1, 2 ]
                

                寄生式组合继承可以算是引用类型继承的最佳继承

                总结

                到此这篇关于JS继承的文章就介绍到这了,更多相关JS继承的理解内容请搜索NICE源码以前的文章或继续浏览下面的相关文章希望大家以后多多支持NICE源码!

                免责声明:
                1、本网站所有发布的源码、软件和资料均为收集各大资源网站整理而来;仅限用于学习和研究目的,您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。 不得使用于非法商业用途,不得违反国家法律。否则后果自负!

                2、本站信息来自网络,版权争议与本站无关。一切关于该资源商业行为与www.niceym.com无关。
                如果您喜欢该程序,请支持正版源码、软件,购买注册,得到更好的正版服务。
                如有侵犯你版权的,请邮件与我们联系处理(邮箱:skknet@qq.com),本站将立即改正。

                NICE源码网 JavaScript 对于JavaScript继承你到底了解多少 https://www.niceym.com/23735.html