js对象继承方式总结

js对象继承方式

原型链继承

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

    // 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

借用构造函数继承

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

    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

组合继承

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

    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() 方法就是原型式继承的实现。缺点与原型链方式相同。

    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"]

寄生式继承

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

    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"

寄生式组合继承

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

    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
  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱写bug的小邓程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值