>웹 프론트엔드 >JS 튜토리얼 >JavaScript_javascript 기술의 세 가지 상속 방법 및 예

JavaScript_javascript 기술의 세 가지 상속 방법 및 예

WBOY
WBOY원래의
2016-05-16 16:17:081141검색

자바스크립트는 객체지향 언어이지만 상속 메커니즘은 처음부터 다른 전통적인 객체지향 언어와 다르지만 프로토타입 기반 상속 메커니즘이지만 여전히 상속이 존재합니다. 이를 구현하는 몇 가지 다른 방법.

방법 1: 클래스 상속

소위 클래스 상속이란 전통적인 객체지향 언어를 모방한 상속 방식을 말합니다. 상속과 상속이 모두 "클래스"입니다.

먼저 상위 클래스(또는 슈퍼 클래스)를 정의합니다.

function Person(name){
    this.name=name;
  }

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

상위 클래스인 person의 속성은 생성자에 정의되어 이를 상속받은 하위 클래스의 name 속성이 이 속성과 공유되지 않고 하위 클래스에만 속하도록 보장합니다. getName 메소드가 마운트됩니다. 프로토타입은 하위 클래스의 여러 인스턴스가 이 메서드 본문을 공유하도록 하여 메모리를 절약할 수 있습니다. (여러 인스턴스의 경우 New 인스턴스가 나올 때마다 이러한 인스턴스의 getName 메서드가 동일한 메모리 공간을 참조하도록 보장됩니다. 별도의 공간보다).

다음과 같이 상속 메서드 확장을 정의합니다.

function extend(subClass,superClass){
    var F=function(){};
    F.prototype=superClass.prototype;
    subClass.prototype=new F();
    subClass.prototype.constructor=subClass;

    subClass.superClass=superClass.prototype;
    if(superClass.prototype.constructor==Object.prototype.constructor){
      superClass.prototype.constructor=superClass;
    }

  }

이 방법에서는 먼저 새 클래스 F를 만들고 그 프로토타입을 부모 클래스의 프로토타입으로 만들고 하위 클래스의 프로토타입이 클래스 F의 인스턴스를 가리키도록 하여 부모 클래스를 상속하는 목적을 달성합니다. 동시에 서브클래스의 프로토타입이 수정되었기 때문에 수정된 프로토타입의 constructor 속성이 서브클래스를 가리키게 되어 생성자를 가지게 되며, 동시에 해당 서브클래스에 superClass 속성이 마운트되며, 이를 통해 하위 클래스가 상위 클래스를 호출하여 하위 클래스와 상위 클래스 간의 관계를 설정할 수 있습니다.

다음과 같이 상위 클래스 Person을 상속하도록 하위 클래스 Author를 정의합니다.

function Author(name,books){
    Author.superClass.constructor.call(this,name);
    this.book=books;
  }
  extend(Author,Person);
  Author.prototype.getBooks=function(){
    return this.book;
  }

여기서 하위 클래스의 생성자에서는 상위 클래스의 생성자가 superClass 속성을 통해 호출되고 호출 메서드를 사용하여 해당 메서드에서 호출된 this 포인터를 변환하므로 하위 클래스 Author도 소유합니다(상속됨). ) 상위 클래스의 속성과 동시에 하위 클래스에도 자체 속성 책이 있으므로 생성자에서는 구성 목적을 달성하기 위해 매개 변수 책을 속성 책에 할당합니다. 부모 클래스인 Person의 프로토타입에 있는 속성과 메서드를 상속하려면 확장 함수를 사용하세요. (이전에는 메서드만 프로토타입에 마운트했고 속성은 생성자에서 정의되었기 때문에 실제로는 메서드만 상속됩니다.) 동시에 Author는 상속을 기반으로 더욱 확장하려는 목적을 달성하기 위해 해당 프로토타입에 마운트되는 자체 메소드 getBooks를 가지고 있습니다.

이 상속 방법은 확실히 전통적인 객체 지향 언어와 유사한 클래스 상속을 사용합니다. 장점은 전통적인 객체 지향 개념에 익숙한 프로그래머가 이해하기 쉽다는 것입니다. 단점은 프로세스가 더 번거롭고 복잡하다는 것입니다. 하위 클래스에도 자체 생성자와 프로토타입이 있고 하위 클래스와 상위 클래스의 속성이 완전히 격리되어 있기 때문에 메모리 소비가 약간 더 큽니다.

방법 2: 프로토타입 상속

먼저 상위 클래스를 정의합니다. 생성자를 사용하여 정의하는 방식을 고의로 모방하지 않고 직접 개체 리터럴을 사용하여 상위 클래스인 개체를 정의합니다.

var Person={
   name:'default name',
   getName:function(){
     return this.name;
   }

 } ;

첫 번째 메소드와 마찬가지로 이 객체에는 속성 이름과 getName 메소드가 있습니다.

그런 다음 다음과 같이 상위 클래스로부터 하위 클래스 상속을 실현하는 복제 메소드를 정의합니다.

function clone(obj){
     function F(){}
     F.prototype=obj;
     return new F();
   }

이 복제 방법은 새 객체를 생성하고 해당 객체의 프로토타입을 매개변수 obj인 상위 클래스를 가리키며 동시에 객체를 반환합니다.

마지막으로 하위 클래스는 다음과 같이 clone 함수를 통해 상위 클래스를 상속받습니다.

 var Author=clone(Person);
 Author.book=['javascript'];
 Author.showBook=function(){
 return this.book;
 }

这里定义一个子类,通过clone函数继承父类Person,同时拓展了一个属性book,和一个方法showBook,这里该子类也拥有属性name,但是它和父类的name值是一样的,所以没有进行覆盖,如果不一样,可以采用

 Author.name='new name';覆盖这个属性,从而得到子类的一个新的name属性值。

这种原型式继承相比于类式继承更为简单自然,同时如果子类的属性和父类属性值相同,可以不进行修改的话,那么它们两者其实共享的是同一段内存空间,如上面的name属性,缺点是对于习惯了传统面向对象的程序员难以理解,如果两者要进行选择的话,无疑是这种方式更为优秀一些。

既然javascript中采用基于原型的方式来实现继承,而且每个对象的原型只能指向某个特定的类的实例(不能指向多个实例),那么如何实现多重继承(即让一个类同时具有多个类的方法和属性,而且本身内部不自己定义这些方法和属性)?

在javascript设计模式中给出了一种掺元类(mixin class)的方式:

首先定义一个掺元类,用来保存一些常用的方法和属性,这些方法和属性可以通过拓展的方式添加到任何其他类上,从而被添加类就具有了该类的某些方法和属性,如果定义多个掺元类,同时添加给一个类,那么该类就是间接实现了“多重继承”,基于这种思想,实现如下:

掺元类定义:

var Mixin=function(){};
  Mixin.prototype={
    serialize:function(){
      var output=[];
      for(key in this){
        output.push(key+":"+this[key]);
      }
      return output.join(',');
    }
  }

该掺元类具有一个serialize方法,用来遍历其自身,输出自身的属性和属性值,并且将他们以字符串形式返回,中间用逗号隔开。

定义一个扩充方法,用来使某个类经过扩充之后具备掺元类的属性或方法,如下:

function augment(receivingClass,givingClass){
    if(arguments[2]){
      for(var i= 2,len=arguments.length;i<len;i++){
        receivingClass.prototype[arguments[i]]=givingClass.prototype[arguments[i]];
      }
    }
    else
    {
      for(methodName in givingClass.prototype){
        if(!receivingClass.prototype[methodName]){
          receivingClass.prototype[methodName]=givingClass.prototype[methodName];
        }
      }

    }
 }

该方法默认是两个参数,第一个参数是接受被扩充的类,第二个参数是掺元类(用来扩充其他类的类),还可以有其他参数,如果大于两个参数,后面的参数都是方法或者属性名,用来表示被扩充类只想继承掺元类的指定的属性或方法,否则默认继承掺元类的所有属性和方法,在该函数中,第一个if分支是用来继承指定属性和方法的情形,else分支是默认继承所有属性和方法的情形。该方法的实质是将掺元类的原型上的属性和方法都扩充(添加)到了被扩充类的原型上面,从而使其具有掺元类的属性和方法。

最后,使用扩充方法实现多重继承

augment(Author,Mixin);
   var author= new Author('js',['javascript design patterns']);
   alert(author.serialize());

这里定义了一个author的类,该类继承自Person父类,同时又具备掺元类Mixin的方法和属性,如果你愿意,可以定义N个掺元类用来扩充该类,它同样能够继承你定义的其他掺元类的属性和方法,这样就实现了多重继承,最后,author的serialize方法的运行结果如下:

你会发现该类同时具有person类,Author类,Mixin类的属性和方法,其中Person和Mixin的属性和方法都是通过“继承”得来的,从实际上来讲,它实现了多重继承。

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.