ES6中類與繼承的理解(java對比記憶)

前言

先上兩段代碼: java中定義類:javascript

public class Person{
    private String name;
    private int age;
   
    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }
    public void getInfo(){ 
        System.out.println(name+age);
    }
}
複製代碼

Es6中定義一個類:html

class Person{
    constructor(name,age){
        this.name=name;
        this.age=age;
    }
    getInfo(){
        return this.name+','+this.age;
    }
}
//調用
let person=new Person("koala","123");
複製代碼

經過上面兩段代碼引出咱們今天要說的相關內容java

類中的變量

  • 兩者異 在java中能夠直接聲明各類類型的私有變量,在ES6中的類不能夠直接在類中聲明私有變量,聲明後會報錯。 注意:可是隨着v8的更新,在node12版本中,ES增長了一些新規範,其中就有支持類的私有變量這一條。 代碼以下:
class Greet {
  #name = 'World';
  get name() {
    return this.#name;
  }
  set name(name) {
    this.#name = name;
  }
  sayHello() {
    console.log(`Hello, ${this.#name}`);
  }
}
複製代碼

在類的外部或去#name變量會拋出異常node

const greet = new Greet()
greet.#name = 'NewName';
// -> SyntaxError
console.log(greet.#name)
// -> SyntaxError
複製代碼

類中的構造函數

  • 兩者同:

若是聲明一個一個類的時候沒有聲明構造函數,那麼會默認添加一個空的構造函數,構造函數在new實例化一個對象的時候會被調用程序員

  • 兩者異:

在ES6中,能夠在構造函數中直接定義類方法(類方法也能夠是箭頭函數),代碼以下面試

constructor(name,age){
          this.name=name;
          this.age=age;
          this.getInfo()=()=>{
              console.log("name"+this.name+"sex"+this.sex);
             }         
 } 
複製代碼

類中的方法

  • 兩者同:

有參,無參函數,函數調用方式相同。靜態方法,ES6中用static聲明一個靜態方法,方法只能用類名直接調用,不能經過類的實例調用微信

  • 兩者異:

ES6在類中聲明函數,無需使用function關鍵字,java的類中必須使用關鍵字聲明函數。koa

ES6方法內部訪問類屬性的時候須要this來訪問,java不須要。函數

ES6的構造函數中能夠定義函數,java不可。學習

類中的繼承

  • 兩者同:

繼承關鍵字都是extends,super方法的使用

  • 兩者異:

繼承的調用:

ES6須要注意的是super只能調用父類方法,而不能調用父類的屬性,方法定義再原型鏈中,屬性定義在類的內部

java中,super關鍵字,能夠經過super關鍵字來實現對父類成員的訪問,用來引用當前對象的父類。

繼承過程當中的構造函數:

ES6中,子類中,super方法是必須調用的,由於子類自己沒有自身的this對象,須要經過super方法拿到父類的this對象。在子類中,沒有構造函數,那麼在默認的構造方法內部自動調用super方法,繼承父類的所有屬性,子類的構造方法中,必須先調用super方法,而後才能調用this關鍵字聲明其它屬性。(子類的this就是在這裏調用super以後,拿到父類的this,而後修改這個this來的)

class Student extends Person{
    constructor(name,sex){
        console.log(this);//Error
        super(name,sex);
        this.sex=sex;
    }
}
複製代碼

java中,子類是不繼承父類的構造器(構造方法或者構造函數)的,它只是調用(隱式或顯式)。若是父類的構造器帶有參數,則必須在子類的構造器中顯式地經過 super 關鍵字調用父類的構造器並配以適當的參數列表。

若是父類構造器沒有參數,則在子類的構造器中不須要使用 super **關鍵字調用父類構造器,系統會自動調用父類的無參構造器。 **

看一段面試問的比較多的代碼實例:

class SuperClass {
  private int n;
  SuperClass(){
    System.out.println("SuperClass()");
  }
  SuperClass(int n) {
    System.out.println("SuperClass(int n)");
    this.n = n;
  }
}
class SubClass extends SuperClass{
  private int n;
  
  SubClass(){
    super(300);
    System.out.println("SubClass");
  }  
  
  public SubClass(int n){
    System.out.println("SubClass(int n):"+n);
    this.n = n;
  }
}
public class TestSuperSub{
  public static void main (String args[]){
    SubClass sc = new SubClass();
    SubClass sc2 = new SubClass(200); 
  }
}
複製代碼

輸出結果:

SuperClass(int n)
SubClass SuperClass() SubClass(int n):200 複製代碼

ES6中的類與原型鏈的關係

看一下文初定義的一個的javascript類。它和原型鏈對等的代碼以下:

//類
class Person{
    constructor(name,age){
        this.name=name;
        this.age=age;
    }
    getInfo(){
        return this.name+','+this.age;
    }
}

//原型鏈
function Person(name, age) {
    this.name = name;
    this.age = age;
}
  
Person.prototype.getInfo = function () {
    return this.name+','+this.age;
};
console.log(Person)
let person = new Person("koala", 123);
複製代碼

針對代碼進行一下說明講解:

  • 聲明的新對象都不具有原型鏈(類)的函數,可是卻能夠調用原型鏈的函數
Object.getOwnPropertyNames(p)//[ 'name', 'age' ] 從輸出結果能夠看出只有這兩個屬性,不具備getInfo函數
console.log(p.getInfo());//輸出結果 kaola,123
複製代碼

無論是在原型鏈仍是類中,獲取的結果都是['name','age']

  • 直接打印class,發現類實際是個函數,就是對應的構造函數,this關鍵字表明實例對象,簡單的說是class就是構造函數,prototype對象的constructor屬性,直接指向「類」的自己。
//直接打印類
console.log(Person);
console.log(Point===Point.prototype.constructor);//true
複製代碼
  • 與ES5同樣,實例的屬性除非顯式定義在其自己(即定義在this對象上),不然都是定義在原型上(即定義在class上)。
person.hasOwnProperty('name') // true
 person.hasOwnProperty('age') // true
 person.hasOwnProperty('getInfo') // false
 person.__proto__.hasOwnProperty('getInfo') // true getInfo是原型對象的屬性
複製代碼
  • 類的全部實例共享一個原型對象
let person1 = new Person("koala1", 124);
console.log(person.__proto__===person1.__proto__);//true
複製代碼
  • 類的實例 構造方法默認返回實例對象(this) 可是返回this能夠修改

ES6中類的出現有什麼好處

  • js中的類仍然是基於原型的。即便在建立類後修改類的構造函數上的原型對象仍然不會有任何問題。 例子代碼以下:
class Foo {
    constructor(name) {
        this.name = name;
    }

    test1() {
        console.log("test1: name = " + this.name);
    }
}
Foo.prototype.test2 = function() {
    console.log("test2: name = " + this.name);
};
複製代碼
  • 類的語法簡單,不易出錯,尤爲是在繼承層次結構上簡單不少。

  • 類保護你免受沒法使用構造函數使用新的常見錯誤(經過讓構造函數拋出異常,若是這不是構造函數的有效對象)。

代碼例子以下: ES6中類出現後實現繼承:

// ES6
class Person {
    constructor(first, last) {
        this.first = first;
        this.last = last;
    }

    personMethod() {
        // ...
    }
}

class Employee extends Person {
    constructor(first, last, position) {
        super(first, last);
        this.position = position;
    }

    employeeMethod() {
        // ...
    }
}

class Manager extends Employee {
    constructor(first, last, position, department) {
        super(first, last, position);
        this.department = department;
    }

    managerMethod() {
        // ...
    }
}
複製代碼

ES6中類未出現前實現繼承:

// ES5
var Person = function(first, last) {
    if (!(this instanceof Person)) {
        throw new Error("Person is a constructor function, use new with it");
    }
    this.first = first;
    this.last = last;
};

Person.prototype.personMethod = function() {
    // ...
};

var Employee = function(first, last, position) {
    if (!(this instanceof Employee)) {
        throw new Error("Employee is a constructor function, use new with it");
    }
    Person.call(this, first, last);
    this.position = position;
};
Employee.prototype = Object.create(Person.prototype);
Employee.prototype.constructor = Employee;
Employee.prototype.employeeMethod = function() {
    // ...
};

var Manager = function(first, last, position, department) {
    if (!(this instanceof Manager)) {
        throw new Error("Manager is a constructor function, use new with it");
    }
    Employee.call(this, first, last, position);
    this.department = department;
};
Manager.prototype = Object.create(Employee.prototype);
Manager.prototype.constructor = Manager;
Manager.prototype.managerMethod = function() {
    // ...
};

複製代碼

附錄:

java中的繼承 www.runoob.com/java/java-i…

以爲本文對你有幫助?請分享給更多人

歡迎你們關注個人公衆號——程序員成長指北,公衆號會一直分享有價值的技術乾貨文章,學習資料,面試等內容,也可加羣共同窗習,共同進步。請自行微信搜索——「程序員成長指北」

個人公衆號.jpg
相關文章
相關標籤/搜索