精华内容
下载资源
问答
  • 寄生组合继承
    2020-08-06 15:17:47

    1、寄生组合式继承, 即通过借用构造函数来继承属性, 在原型上添加共用的方法, 通过寄生式实现继承

    2、

    			//寄生组合式继承, 即通过借用构造函数来继承属性, 在原型上添加共用的方法, 通过寄生式实现继承.
    			// 上边的例子高效的体现了只调用了一次 SuperType 构造函数,并且因此也避免了在 SubType.prototype 上面创建不必要的 多余的属性.与此同时,原型链还能保持不变
    			// function inheritPrototype(subType, superType) {
    			// 	var prototype = Object.create(superType.prototype); // 创建对象,创建父类原型的一个副本
    			// 	prototype.constructor = subType; // 增强对象,弥补因重写原型而失去的默认的constructor 属性
    			// 	subType.prototype = prototype; // 指定对象,将新创建的对象赋值给子类的原型
    			// }
    
    
    			// 父类初始化实例属性和原型的属性和方法
    			function SuperType(name) {
    				this.name = name;
    				this.colors = ["red", "blue", "green"];
    				this.sheet = function(sheet) {
    					console.log(this.name + '正在sheet!' + sheet);
    				}
    			}
    			SuperType.prototype.sayName = function() {
    				console.log(this.name);
    			};
    
    			// 借用构造函数继承构造函数的实例的属性(解决引用类型共享的问题)
    			function SubType(name, age) {
    				SuperType.call(this, name);
    				this.age = age;
    			}
    
    			(function(SubType, SuperType) {
    				var prototype = Object.create(SuperType.prototype) //创建父类原型的一个副本
    				prototype.constructor = prototype // 增强对象,弥补因重写原型而失去的默认的constructor 属性
    				SubType.prototype = prototype //指定对象,讲新创建的对象赋值给子类的原型
    			}(SubType, SuperType))
    			// 将子类型的原型重写替换成父类的原型
    			
    			// inheritPrototype(SubType, SuperType);
    
    			// 对子类添加自己的方法
    			SubType.prototype.sayAge = function() {
    				console.log(this.age);
    			};
    
    			var instance1 = new SubType("heyushuo", 12);
    			var instance2 = new SubType("kebi");
    			console.log('instance1', instance1)
    			console.log('instance2', instance2)
    			instance1.sayName(); //heyushuo
    			instance1.sayAge(); //12
    			instance2.sayName(); //kebi
    
    			instance1.colors.push("yellow"); // ["red", "blue", "green", "yellow"]
    			instance1.colors.push("black"); // ["red", "blue", "green", "black"]
    

     

    更多相关内容
  • 继承 子类能够使用父类的属性和方法 原型链继承 创建人的类 function Person(name, age) { this.name = name this.age = age } Person.prototype.say = function () { console.log('说话了') } const p1 = ...

    继承

    子类能够使用父类的属性和方法

    原型链继承

    1. 创建人的类

      function Person(name, age) {
        this.name = name
        this.age = age
      }
      
      Person.prototype.say = function () {
        console.log('说话了')
      }
      
      const p1 = new Person('张三', 19)
      
    2. 创建狗的类

      function Dog(name, age) {
        this.name = name
        this.age = age
      }
      
      Dog.prototype.say = function () {
        console.log('说话了')
      }
      
      const d1 = new Dog('大黄', 3)
      
    3. 狗继承自人的类

      // 创建人的类
      function Person(name, age) {
        this.name = name
        this.age = age
      }
      
      Person.prototype.say = function () {
        console.log('说话了')
      }
      function Dog() {
      }
      
      // 此方式不推荐 子原型和父原型公用同一个原型
      // Dog.prototype = Person.prototype
      Dog.prototype = new Person()
      
      const d1 = new Dog('大黄', 3)
      

    以上则实现原型链继承但是会有以下问题:

    • 包含引用类型值的原型属性会被所有的实例共享

      function Person(name, age) {
        this.name = name
        this.age = age
        this.hobby = []
      }
      
    • 创建子类的时候不能传递参数

    借用构造函数继承

    1. 创建人的类

      // 创建人的类
      function Person(name, age) {
        this.name = name
        this.age = age
        this.hobby = []
      }
      
    2. 通过call实现

      function Dog(name, age) {
        Person.call(this, name, age)
      }
      
      const d1 = new Dog('大黄', 2)
      const d2 = new Dog('小黄', 1)
      d1.hobby = '吃吃吃'
      

    组合式继承

    // 创建人的类
    function Person(name, age) {
      this.name = name
      this.age = age
    }
    
    Person.prototype.say = function () {
      console.log('说话了')
    }
    function Dog(name,age) {
      Person.call(this,name,age)
    }
    
    // 此方式不推荐 子原型和父原型公用同一个原型
    // Dog.prototype = Person.prototype
    Dog.prototype = new Person()
    
    const d1 = new Dog('大黄', 3)
    const d2 = new Dog('小黄', 2)
    

    寄生式组合继承

    Object.create作用:

    1. 创建对象
    2. 将对象的__proto__ 指向参数对象
    // 创建人的类
    function Person(name, age) {
      this.name = name
      this.age = age
    }
    
    Person.prototype.say = function () {
      console.log('说话了')
    }
    function Dog(name,age) {
      Person.call(this,name,age)
    }
    
    // 此方式不推荐 子原型和父原型公用同一个原型
    // Dog.prototype = Person.prototype
    Dog.prototype = Object.create(Person.prototype)
    
    const d1 = new Dog('大黄', 3)
    const d2 = new Dog('小黄', 2)
    

    es6类继承

    class Person {
      say () {
        console.log('说话了')
      }
    }
    
    class Child extends Person {
    }
    
    const child = new Child()
    child.say()
    
    展开全文
  • 说实在话,以前我只需要知道“寄生组合继承”是最好的,有个祖传代码模版用就行。最近因为一些事情,几个星期以来一直心心念念想整理出来。本文以《JavaScript高级程序设计》上的内容为骨架,补充了ES6 Class的相关...
    免费帮忙内推阿里等各大IT公司的岗位,有兴趣可以带简历加微信angeltune
    说实在话,以前我只需要知道“寄生组合继承”是最好的,有个祖传代码模版用就行。最近因为一些事情,几个星期以来一直心心念念想整理出来。本文以《JavaScript高级程序设计》上的内容为骨架,补充了ES6 Class的相关内容,从我认为更容易理解的角度将继承这件事叙述出来,希望大家能有所收获。

    1. 继承分类

    先来个整体印象。如图所示,JS中继承可以按照是否使用object函数(在下文中会提到),将继承分成两部分(Object.create是ES5新增的方法,用来规范化这个函数)。

    其中,原型链继承和原型式继承有一样的优缺点,构造函数继承与寄生式继承也相互对应。寄生组合继承基于Object.create, 同时优化了组合继承,成为了完美的继承方式。ES6 Class Extends的结果与寄生组合继承基本一致,但是实现方案又略有不同。

    下面马上进入正题。

    clipboard.png

    2. 继承方式

    上图上半区的原型链继承,构造函数继承,组合继承,网上内容比较多,本文不作详细描述,只指出重点。这里给出了我认为最容易理解的一篇《 JS中的继承(上)》。如果对上半区的内容不熟悉,可以先看这篇文章,再回来继续阅读;如果已经比较熟悉,这部分可以快速略过。另,上半区大量借用了yq前端的一篇继承文章[1]。

    2.1 原型链继承

    核心:将父类的实例作为子类的原型

    SubType.prototype = new SuperType() 
    // 所有涉及到原型链继承的继承方式都要修改子类构造函数的指向,否则子类实例的构造函数会指向SuperType。
    SubType.prototype.constructor = SubType;

    优点:父类方法可以复用
    缺点:

    • 父类的引用属性会被所有子类实例共享
    • 子类构建实例时不能向父类传递参数

    2.2 构造函数继承

    核心:将父类构造函数的内容复制给了子类的构造函数。这是所有继承中唯一一个不涉及到prototype的继承。

    SuperType.call(SubType);

    优点:和原型链继承完全反过来。

    • 父类的引用属性不会被共享
    • 子类构建实例时可以向父类传递参数

    缺点:父类的方法不能复用,子类实例的方法每次都是单独创建的。

    2.3 组合继承

    核心:原型式继承和构造函数继承的组合,兼具了二者的优点。

    function SuperType() {
        this.name = 'parent';
        this.arr = [1, 2, 3];
    }
    
    SuperType.prototype.say = function() { 
        console.log('this is parent')
    }
    
    function SubType() {
        SuperType.call(this) // 第二次调用SuperType
    }
    
    SubType.prototype = new SuperType() // 第一次调用SuperType

    优点:

    • 父类的方法可以被复用
    • 父类的引用属性不会被共享
    • 子类构建实例时可以向父类传递参数

    缺点:
    调用了两次父类的构造函数,第一次给子类的原型添加了父类的name, arr属性,第二次又给子类的构造函数添加了父类的name, arr属性,从而覆盖了子类原型中的同名参数。这种被覆盖的情况造成了性能上的浪费。

    2.4 原型式继承

    核心:原型式继承的object方法本质上是对参数对象的一个浅复制。
    优点:父类方法可以复用
    缺点:

    • 父类的引用属性会被所有子类实例共享
    • 子类构建实例时不能向父类传递参数
    function object(o){
      function F(){}
      F.prototype = o;
      return new F();
    }
    
    var person = {
        name: "Nicholas",
        friends: ["Shelby", "Court", "Van"]
    };
    
    var anotherPerson = object(person);
    anotherPerson.name = "Greg";
    anotherPerson.friends.push("Rob");
    
    var yetAnotherPerson = object(person);
    yetAnotherPerson.name = "Linda";
    yetAnotherPerson.friends.push("Barbie");
    alert(person.friends);   //"Shelby,Court,Van,Rob,Barbie"
    
    ECMAScript 5 通过新增 Object.create()方法规范化了原型式继承。这个方法接收两个参数:一 个用作新对象原型的对象和(可选的)一个为新对象定义额外属性的对象。在传入一个参数的情况下, Object.create()与 object()方法的行为相同。——《JAVASCript高级编程》

    所以上文中代码可以转变为

    var yetAnotherPerson = object(person); => var yetAnotherPerson = Object.create(person);

    2.5 寄生式继承

    核心:使用原型式继承获得一个目标对象的浅复制,然后增强这个浅复制的能力。
    优缺点:仅提供一种思路,没什么优点

    function createAnother(original){ 
        var clone=object(original);    //通过调用函数创建一个新对象
        clone.sayHi = function(){      //以某种方式来增强这个对象
            alert("hi");
        };
        return clone;                  //返回这个对象
    }
    
    var person = {
        name: "Nicholas",
        friends: ["Shelby", "Court", "Van"]
    };
    
    var anotherPerson = createAnother(person);
    anotherPerson.sayHi(); //"hi"

    2.6 寄生组合继承

    刚才说到组合继承有一个会两次调用父类的构造函数造成浪费的缺点,寄生组合继承就可以解决这个问题。

    function inheritPrototype(subType, superType){
        var prototype = object(superType.prototype); // 创建了父类原型的浅复制
        prototype.constructor = subType;             // 修正原型的构造函数
        subType.prototype = prototype;               // 将子类的原型替换为这个原型
    }
    
    function SuperType(name){
        this.name = name;
        this.colors = ["red", "blue", "green"];
    }
    
    SuperType.prototype.sayName = function(){
        alert(this.name);
    };
    
    function SubType(name, age){
        SuperType.call(this, name);
        this.age = age;
    }
    // 核心:因为是对父类原型的复制,所以不包含父类的构造函数,也就不会调用两次父类的构造函数造成浪费
    inheritPrototype(SubType, SuperType);
    SubType.prototype.sayAge = function(){
        alert(this.age);
    }

    优缺点:这是一种完美的继承方式。

    2.7 ES6 Class extends

    核心: ES6继承的结果和寄生组合继承相似,本质上,ES6继承是一种语法糖。但是,寄生组合继承是先创建子类实例this对象,然后再对其增强;而ES6先将父类实例对象的属性和方法,加到this上面(所以必须先调用super方法),然后再用子类的构造函数修改this。

    class A {}
    
    class B extends A {
      constructor() {
        super();
      }
    }

    ES6实现继承的具体原理:

    class A {
    }
    
    class B {
    }
    
    Object.setPrototypeOf = function (obj, proto) {
      obj.__proto__ = proto;
      return obj;
    }
    
    // B 的实例继承 A 的实例
    Object.setPrototypeOf(B.prototype, A.prototype);
    
    // B 继承 A 的静态属性
    Object.setPrototypeOf(B, A);
    

    ES6继承与ES5继承的异同:
    相同点:本质上ES6继承是ES5继承的语法糖
    不同点:

    • ES6继承中子类的构造函数的原型链指向父类的构造函数,ES5中使用的是构造函数复制,没有原型链指向。
    • ES6子类实例的构建,基于父类实例,ES5中不是。

    3. 总结

    • ES6 Class extends是ES5继承的语法糖
    • JS的继承除了构造函数继承之外都基于原型链构建的
    • 可以用寄生组合继承实现ES6 Class extends,但是还是会有细微的差别

    参考文章:

    [1]《js继承、构造函数继承、原型链继承、组合继承、组合继承优化、寄生组合继承
    [2]《JavaScript高级编程》

    展开全文
  • JavaScript继承机制: JavaScript是基于原型链继承的语言,当访问一个属性或者方法的时候,js会沿着原型链依次往上寻找,直到找到相关的值,或者查找到Object.proto === null, 返回undefined值。 有时候,可能需要...

    JavaScript继承机制: JavaScript是基于原型链继承的语言,当访问一个属性或者方法的时候,js会沿着原型链依次往上寻找,直到找到相关的值,或者查找到Object.proto === null, 返回undefined值。

    有时候,可能需要我们自己去实现类之间的继承,下面是几种继承方法,从上往下,继承方式呈逐渐优化趋势。

    父函数和子函数

    // 父函数
    function Person(sex) {
        this.sex = sex
        console.log(count++)
    }
    // 父函数原型链方法
    Person.prototype.showSex = function () {
        console.log(this.sex)
    }
    // 子函数
    function People(name, age) {
        this.name = name
        this.age = age
    }
    // 子函数原型链方法
    People.prototype.sayHi = function () {
        console.log(`hi~, I am a ${this.sex === 'femal' ? 'girl': 'boy'} my name is ${this.name}, and I am ${this.age} years old`)
    }
    

    构造函数继承

    function People(name, age) {
        this.name = name
        this.age = age
        Person.call(this, 'femal')
    }
    

    不能继承父类的原型链方法,只能实现构造函数的继承

    原型链继承

    Person.prototype = new Person('femail')
    // 添加子函数原型链方法
    People.prototype.sayHi = function () {
        console.log(`hi~, I am a ${this.sex === 'femal' ? 'girl': 'boy'} my name is ${this.name}, and I am ${this.age} years old`)
    }
    

    只能继承原型链上的继承,父类构造函数里的数据会丢失掉

    组合继承

    // 继承父类构造函数
    function People(name, age) {
        this.name = name
        this.age = age
        Person.call(this, 'femal')
    }
    // 继承父类原型链
    Person.prototype = new Person('femail')
    // 添加子函数原型链方法
    People.prototype.sayHi = function () {
        console.log(`hi~, I am a ${this.sex === 'femal' ? 'girl': 'boy'} my name is ${this.name}, and I am ${this.age} years old`)
    }
    

    同是继承了父类的构造函数和原型链,但是父类的构造函数实例化了两次,造成了不必要的消耗

    寄生式继承

    // 寄生式继承,通过一个中间值,实现子类原型对象向父类原型对象的指向
    // supClass:Constructor 父类
    // subClass: Constructor 子类
    function inherite(supClass, subClass) {
        let prop = Object.create(supClass).prototype
        prop.constructor = subClass
        subClass.prototype = prop
    }
    
    // 子类,完成构造函数的继承
    function People(name, age) {
        this.name = name
        this.age = age
        Person.call(this, 'femal')
    }
    

    完美!

    展开全文
  • 主要介绍了JavaScript继承基础讲解,原型链、借用构造函数、混合模式、原型式继承、寄生式继承寄生组合继承,需要的朋友可以参考下
  • 下面小编就为大家带来一篇浅谈JS继承_寄生式继承 & 寄生组合继承。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • JS寄生组合继承

    2022-02-27 11:11:57
    寄生组合继承 就是 组合继承 + 原型继承 的结合体 js内部会把这个寄生组成封装成 extend function Father(name) { this.name = name this.hbody = ['吃饭', '睡觉', '打豆豆'] } Father.prototype.getName = ...
  • 原型式继承 原理等同ES5的Object.create()方法, 创建一个函数,使这个函数成为括号中obj的构造函数,也就是这个函数的原型指向这个obj 然后返回这个构造函数的实例,是一个浅拷贝,新实例的引用数据类型改变会让...
  • JS基础--组合继承寄生组合式继承

    千次阅读 2019-05-13 17:03:29
    组合继承使用原型链实现对原型属性和方法的继承,使用借用构造函数实现对实例属性的继承(引用类型的属性写在构造函数里)。 示例: function SuperType (name) { this.name = name; this.colors = ["red", "green...
  • js组合继承和组合寄生继承 js设计之初是没有继承的概念的,如果要实现ES6中class A extends B的形式,需要借用prototype和Function.prototype.apply()方法或Function.prototype.call()方法。 原型链继承方式:B....
  • 在之前javascript面向对象系列的文章里面,我们已经探讨了组合继承寄生继承,回顾下组合继承: function Person( uName ){ this.skills = [ 'php', 'javascript' ]; this.userName = uName; } Person....
  • 继承本质上就是一个对象复用另一个对象的属性和方法,注意,属性和方法的复用效果是不同的,从这点出发去理解继承,也就能理解为什么会产生六种继承
  • 组合继承(伪经典继承) 组合继承综合了原型链和盗用构造函数,解决了原型内引用值共享的问题,以及子类在实例化时不能给父类构造函数传参的问题。 缺点: 调用了两次父类构造函数影响效率,而且子类的...寄生组合继承
  • 主要介绍了JavaScript寄生组合继承,结合实例形式详细分析了寄生组合继承原理、实现方法与相关注意事项,需要的朋友可以参考下
  • 组合继承和寄生组合继承 继承的几种方式在这里就不过多赘述查看js继承方式 这里着重记录一下组合继承和寄生继承的区别 组合继承 function Person(name) { this.name = name, this.age = '23' } Person.prototype...
  • js继承之寄生组合继承 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" ...
  • JS-寄生组合继承

    2021-12-25 12:26:29
    js的继承组合继承-es6之前最佳继承方式
  • 前面说过,组合继承是JavaScript最常用的继承方式;不过,它也有自己的不足。组合继承最大的问题就是无论什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数的内部。...
  • 主要介绍了JavaScript寄生组合继承,结合实例形式分析了javascript寄生组合继承的原理、定义与简单使用方法,需要的朋友可以参考下

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,906
精华内容 3,162
关键字:

// 寄生组合继承