原型链的继承

原型链的问题

原型链的作用很强大,可以用来实现继承,但是也会有一些问题,最大的问题就是引用类型值得原型属性会被所有实例共享

实例是什么? 实例就是 new 对象名称() ; 例如: var instance=new Person();  instance就是实例;

例如:

    var SuperType=function(){
      this.colors=["red","black"];
    }
    var SubType=function(){};
    SubType.prototype=new SuperType();//继承

    var subType=new SubType();
    subType.colors.push("green");
    console.log(subType.colors);

    var subType2=new SubType();
    console.log(subType2.colors);

这段代码输出结果都是:"red","black","green"

这是怎么回事了?

这是因为SubType的所有实例都会共享colors属性,而我们对subType.colors的修改,能够通过subtype2.colors反映出来。

借用构造函数

在解决原型中引用类型值得问题中,可以通过借用构造函数的技术来实现;即:就是通过子类型的构造函数调用父类的构造函数(可以通过call或者apply调用父类构造函数)

以上面的例子改成如下:

var SuperType=function(){
      this.colors=["red","black"];
    }
    var SubType=function(){
        SuperType.call(this) //调用父类的构造函数
    };
    SubType.prototype=new SuperType();//继承

    var subType=new SubType();
    subType.colors.push("green");
    console.log(subType.colors);

    var subType2=new SubType();
    console.log(subType2.colors);

输出的结果为:"red","black","green"

"red","black"

这样我们实际是在(未来将要)新创建的SubType实例环境下调用了SupType构造函数

这样就会在新的SubType对象上执行SuperType函数,而SubType的每个实例都会具有colors属性的副本;

最基本的原型继承

       var Parent=function(name){
             this.name=name || "parent";
       }

       Parent.prototype.getName=function(){
             return this.name;
       }

       var Child=function(name,age){
              this.name=name;
              this.age=age;
       }

       Child.prototype=new Parent();//通过此种方法继承

       var parent=new Parent("this is a parent");
       var child=new Child("I‘m a child",22);
       console.log(parent.getName()); //this is a parent
       console.log(child.getName());//I‘m a child
       console.log(child.age);//22

这种优点是简单,缺点是如果子类需要做跟父类构造函数中相同的初始化动作,需要在子类的构造函数中再重新做一遍,例如:Child中初始化name

如果初始化工作不断增加,这种方式很不方便;

这时候可以借用构造函数,例如:

        var Parent=function(name){
              this.name=name || "parent";
         }

         Parent.prototype.getName=function(){
              return this.name;
         }

         Parent.prototype.obj={a:1};

         var Child=function(name,age){
              //通过apply调用父类构造函数进行初始化工作
              //这样不管父类执行多少初始化工作,子类也可以执行同样的初始化工作
              Parent.apply(this,arguments);
              this.age=age;
         }

         Child.prototype=new Parent();
         //Child.prototype=Parent.prototype;

         var child=new Child("alice",22);
         var parent=new Parent("stone");
         console.log(child.getName());
         console.log(parent.getName());

这种方式可以解决初始化的问题,但是父类构造函数会被执行两次,一次在子类构造函数中,一次是在赋值子类原型链中,

可以通过

        Child.prototype=Parent.prototype;//代替 Child.prototype=new Parent();

即子类和父类指向相同的原型链,但是这样会存在一个问题,修改子类的原型链,会影响父类的原型链,例如:

  var Parent=function(name){
              this.name=name || "parent";
         }

         Parent.prototype.getName=function(){
              return this.name;
         }

         Parent.prototype.obj={a:1};

         var Child=function(name,age){
              //通过apply调用父类构造函数进行初始化工作
              //这样不管父类执行多少初始化工作,子类也可以执行同样的初始化工作
              Parent.apply(this,arguments);
              this.age=age;
         }

         Child.prototype=new Parent();
         //Child.prototype=Parent.prototype;

         var child=new Child("alice",22);
         var parent=new Parent("stone");
         console.log(child.getName());
         console.log(parent.getName());

         Child.prototype.obj.a=26;
         console.log(child.obj.a);//26
         console.log(parent.obj.a);//26

当我改变 Child.prototype.obj.a时,会同时改变父类的原型链。

那又什么好的办法?

时间: 2024-11-12 07:03:15

原型链的继承的相关文章

对Javascript的原型,原型链和继承的个人理解

继承是OO语言中一个最为人津津乐道的概念,也是初接触Javascript的初学者难理解的概念=.=继承主要分为两种:一种是接口继承,另一种是实现继承.而在ECMAScript中只支持实现继承,所以我们今天来讨论讨论实现继承.实现继承就是继承实际的方法,主要依靠原型链来实现.讲到这里我们就需要讨论讨论什么是原型链. 1.什么是原型 要理解原型链我们首先要知道什么是原型.我们知道每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,这个对象包含所有实例共享的属性和方法.所以我个人

原型链的继承都发生在构造函数上

网上的一道题目:var M = function() { this.person = "life" }, N = function() { this.gate = "ok" }; var k = new M(), l = new N(); k.__proto__ = l; console.log(k.gate); 这么写是有问题的. _proto_和prototype的区别. 首先应该是 k.prototype ...原型链的继承都是基本都是发生在构造函数上的,所以

深入理解JS原型链与继承

我 觉得阅读精彩的文章是提升自己最快的方法,而且我发现人在不同阶段看待同样的东西都会有不同的收获,有一天你看到一本好书或者好的文章,请记得收藏起来, 隔断时间再去看看,我想应该会有很大的收获.其实今天要讨论的主题,有许多人写过许多精彩的文章,但是今天我还是想把自己的理解的知识记录下来.我在学习 掌握JS原型链和继承的时候,就是看得@阮一峰老师的写的文章,觉得他写的技术类的文章都容易让理解,简明概要,又好理解.他是我学习JS路程里面一个比较佩服的导师,昨天重新看了他写的<Javascript 面向

小谈js原型链和继承

原型(prototype)在js中可是担当着举足轻重的作用,原型的实现则是在原型链的基础上,理解原型链的原理后,对原型的使用会更加自如,也能体会到js语言的魅力. 本文章会涉及的内容 原型及原型对象 原型链(JavaScript核心部分) 类的继承 instanceof constructor 我们先用一个构造器来实现一个构造函数: function A(){ this.mark = "A"; this.changeMark = function(){ this.mark += &qu

js原型链与继承(初体验)

js原型链与继承是js中的重点,所以我们通过以下三个例子来进行详细的讲解. 首先定义一个对象obj,该对象的原型为obj._proto_,我们可以用ES5中的getPrototypeOf这一方法来查询obj的原型,我们通过判断obj的原型是否与Object.prototype相等来证明是否存在obj的原型,答案返回true,所以存在.然后我们定义一个函数foo(),任何一个函数都有它的prototype对象,即函数的原型,我们可以在函数的原型上添加任意属性,之后通过new一个实例化的对象可以共享

js原型链与继承

先看看JAVA中继承的定义 :Java继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类. 所以继承需要实现的是:能够拥有父类的方法和属性,也能自己定义新的方法和属性; 那么直接用原型链会有什么问题? //定义一个CarModel类 function CarModel(c){ this.color=c||"白色"; this.getColor=function(){ console.log('我的颜色是'+

浅谈js原型链与继承

js原型链与继承是js中的重点,所以我们通过以下三个例子来进行详细的讲解. 首先定义一个对象obj,该对象的原型为obj._proto_,我们可以用ES5中的getPrototypeOf这一方法来查询obj的原型,我们通过判断obj的原型是否与Object.prototype相等来证明是否存在obj的原型,答案返回true,所以存在.然后我们定义一个函数foo(),任何一个函数都有它的prototype对象,即函数的原型,我们可以在函数的原型上添加任意属性,之后通过new一个实例化的对象可以共享

JavaScript难点系列(六):原型链与继承

类和构造函数 JS中使用构造函数来定义类: function Range(from, to) { this.from = from this.to = to } Range.prototype.includes = function(x) { return this,from <= x && x <= this.to } Range.prototype.toString = function() { return this.from + '...' + this.to } va

对Javascript 类、原型链、继承的理解

一.序言 ??和其他面向对象的语言(如Java)不同,Javascript语言对类的实现和继承的实现没有标准的定义,而是将这些交给了程序员,让程序员更加灵活地(当然刚开始也更加头疼)去定义类,实现继承.(以下不讨论ES6中利用class.extends关键字来实现类和继承:实质上,ES6中的class.extends关键字是利用语法糖实现的) Javascript灵活到甚至可以实现接口的封装(类似Java中的Interface和implements). 二.类的实现 1.我对类的理解 ??首先,

JavaScript原型链和继承

1.概念 JavaScript并不提供一个class的实现,在ES6中提供class关键字,但是这个只是一个语法糖,JavaScript仍然是基于原型的.JavaScript只有一种结构:对象.每个对象都有一个私有属性:_proto_,这个属性指向它构造函数的原型对象(property).它的原型对象也有一个属于自己的原型对象,这样层层向上知道一个对象的属性为null.根据定义null没有原型,它是这个原型链中的最后一个环节. 几乎所有的JavaScript中的对象都是位于原型链顶端的Objec