js对象继承方式总结

js对象继承方式

原型链继承

第一种是以原型链的方式来实现继承,但是这种实现方式存在的缺点 是,在包含有引用类型 的数据时,会被所有的实例对象所共享 ,容易造成修改的混乱。还有就是在创建子类型的时候不能向超类型传递参数。

javascript 复制代码
    // 1. 原型链继承
    function Parent() {
      this.colors = ["red", "blue", "green"];
    }

    Parent.prototype.getColors = function () {
      return this.colors;
    };

    function Child() { }

    // 继承了 Parent
    // new的过程中,会把左边这个对象的__proto__属性指向右边这个对象
    Child.prototype = new Parent();

    var instance1 = new Child();
    instance1.colors.push("black");
    console.log(instance1.getColors()); // ["red", "blue", "green", "black"]

    var instance2 = new Child();
    console.log(instance2.getColors()); // ["red", "blue", "green", "black"]

    console.log(instance1.__proto__ === Child.prototype); // true
    console.log(instance1.__proto__.__proto__ === Parent.prototype); // true

借用构造函数继承

第二种方式是使用借用构造函数的方式,这种方式是通过在子类型的函数中调用超类型的构造函数 来实现的,这一种方法解决了不能向超类型传递参数的缺点,但是它存在的一个问题就是无法实现函数方法的复用,并且超类型原型定义的方法子类型也没有办法访问到。

javascript 复制代码
    function Parent(name) {
      this.name = name;
    }

    function Child(name) {
      // 继承了 Parent,同时还传递了参数
      Parent.call(this, name);
    }

    var instance = new Child("John");
    console.log(instance.name); // John
	console.log(instance.sayHello()); // Hello, John!
    console.log(instance instanceof Parent); // false
    console.log(instance.__proto__ === Child.prototype); // true
    console.log(Child.prototype.__proto__ === Parent.prototype); // false

组合继承

第三种方式是组合继承,组合继承是将原型链和借用构造函数组合起来使用的一种方式。通过借用构造函数的方式来实现类型的属性的继承,通过将子类型的原型设置为超类型的实例来实现方法的继承。这种方式解决了上面的两种模式单独使用时的问题,但是由于我们是以超类型的实例来作为子类型的原型,所以调用了两次超类的构造函数,造成了子类型的原型中多了很多不必要的属性。

javascript 复制代码
    function Parent(name) {
      this.name = name;
      this.colors = ["red", "blue", "green"];
    }

    Parent.prototype.sayName = function () {
      console.log(this.name);
    };

    function Child(name, age) {
      // 继承属性
      Parent.call(this, name);
      this.age = age;
    }

    // 继承方法
    Child.prototype = new Parent();
    Child.prototype.constructor = Child;
    Child.prototype.sayAge = function () {
      console.log(this.age);
    };

原型式继承

第四种方式是原型式继承,原型式继承的主要思路就是基于已有的对象来创建新的对象,实现的原理是,向函数中传入一个对象,然后返回一个以这个对象为原型的对象。这种继承的思路主要不是为了实现创造一种新的类型,只是对某个对象实现一种简单继承,ES5 中定义的 Object.create() 方法就是原型式继承的实现。缺点与原型链方式相同。

javascript 复制代码
    var person = {
      name: "John",
      friends: ["Shelby", "Court", "Van"]
    };

    var anotherPerson = Object.create(person);
    anotherPerson.name = "Greg";
    anotherPerson.friends.push("Rob");

    var yetAnotherPerson = Object.create(person);
    yetAnotherPerson.name = "Linda";
    yetAnotherPerson.friends.push("Barbie");

    console.log(person.friends); // ["Shelby", "Court", "Van", "Rob", "Barbie"]

寄生式继承

第五种方式是寄生式继承,寄生式继承的思路是创建一个用于封装继承过程的函数,通过传入一个对象,然后复制一个对象的副本,然后对象进行扩展,最后返回这个对象。这个扩展的过程就可以理解是一种继承。这种继承的优点就是对一个简单对象实现继承,如果这个对象不是自定义类型时。缺点是没有办法实现函数的复用。

javascript 复制代码
    function createAnother(original) {
      var clone = Object.create(original); // 通过调用函数创建一个新对象
      clone.sayHi = function () { // 以某种方式来增强这个对象
        console.log("hi");
      };
      return clone; // 返回这个对象
    }

    var person = {
      name: "John",
      friends: ["Shelby", "Court", "Van"]
    };

    var anotherPerson = createAnother(person);
    anotherPerson.sayHi(); // "hi"

寄生式组合继承

第六种方式是寄生式组合继承,组合继承的缺点就是使用超类型的实例做为子类型的原型,导致添加了不必要的原型属性。寄生式组合继承的方式是使用超类型的原型的副本来作为子类型的原型,这样就避免了创建不必要的属性。

javascript 复制代码
    function inheritPrototype(Child, Parent) {
      var prototype = Object.create(Parent.prototype); // 创建对象
      prototype.constructor = Child; // 增强对象
      Child.prototype = prototype; // 指定对象
    }

    function Parent(name) {
      this.name = name;
      this.colors = ["red", "blue", "green"];
    }

    Parent.prototype.sayName = function () {
      console.log(this.name);
    };

    function Child(name, age) {
      Parent.call(this, name); // 第二次调用 Parent()
      this.age = age;
    }

    inheritPrototype(Child, Parent);

    Child.prototype.sayAge = function () {
      console.log(this.age);
    };

    var instance = new Child("John", 29);
    instance.sayName(); // John
    instance.sayAge(); // 29
相关推荐
伟笑13 分钟前
elementUI 循环出来的表单,怎么做表单校验?
前端·javascript·elementui
确实菜,真的爱37 分钟前
electron进程通信
前端·javascript·electron
魔术师ID2 小时前
vue 指令
前端·javascript·vue.js
Clown953 小时前
Go语言爬虫系列教程 实战项目JS逆向实现CSDN文章导出教程
javascript·爬虫·golang
星空寻流年3 小时前
css3基于伸缩盒模型生成一个小案例
javascript·css·css3
waterHBO5 小时前
直接从图片生成 html
前端·javascript·html
EndingCoder5 小时前
JavaScript 时间转换:从 HH:mm:ss 到十进制小时及反向转换
javascript
互联网搬砖老肖5 小时前
React组件(一):生命周期
前端·javascript·react.js
HCl+NaOH=NaCl+H_2O5 小时前
Quasar组件 Carousel走马灯
javascript·vue.js·ecmascript
℘团子এ6 小时前
vue3中预览Excel文件
前端·javascript