ES6 class characteristics

概述

class (類)做爲對象的模板被引入,能夠經過 class 關鍵字定義類。類簡要說明
類的本質是function,是基本原型繼承的語法糖。因此,JS中繼承的模型是不會被改變的。
類既然是函數,那與函數有何不一樣呢?咱們爲何要使用類呢?
有時間,先看一下MDN odhtml

  • 函數聲明能夠被提高,而類聲明與let/const 聲明相似,不能被提高,也就是在真正執行聲明以前,它們會一直存在於臨時死區中。
  • 類聲明中的全部代碼將自動運行在嚴格模式下,並且沒法強行讓代碼脫離嚴格模式。
  • 類中的全部方法,都是不可枚舉的。而普通自定義類型中,必須經過Object.defineProperty()方法來指定某方法不可枚舉。
  • 每一個類都有一個[[Construct]]的內部方法,經過關鍵字new調用那些不含[[Construct]]的方法會致使程序拋出錯誤。
  • 使用除關鍵字new以外的方式調用構造函數會致使程序拋出錯誤。
  • 在類中修改類名會致使程序報錯。

類聲明

首先class關鍵字,而後是類的名字,其它部分的語法,相似於對象字面量方法的簡寫形式,但不須要在各元素之間使用逗號分隔。es6

class HelloClass {
    constructor(greeting) {
        this.greeting = greeting;
    }
    
    sayGreeting(){
        console.log(this.greeting);
    }
}

let hello = new HelloClass('Hello');
hello.sayGreeting();  // Hello

console.log(hello instanceof HelloClass);  // true
console.log(hello instanceof Object);  // true

console.log(typeof HelloClass);  // function
console.log(typeof HelloClass.prototype.sayGreeting); // function

分析:函數

  1. constructor爲保留方法名,是用來構建對象的,不可用做其它用途。
  2. 函數定義以前,不須要添加function關鍵字。
  3. 類的屬性不可被賦予新值,HelloClass.prototype是一個只可讀類屬性。

與之等價的ES5聲明this

let HelloClass = (function(){
    "use strict";
    const HelloClass  = function(greeting) {
        if (typeof new.target === 'undefined') {
            throw new Error("必須經過關鍵字new調用構造函數");
        }
        this.greeting = greeting;

        Object.defineProperty(HelloClass.prototype, "sayGreeting", {
            value: function() {
                if (typeof new.target !== 'undefined') {
                    throw new Error("不可以使用關鍵字new調用構造函數");
                }
                console.log(this.greeting);
            },
            enumerable: false,
            writable: true,
            configurable: true
        });        
    }
    return HelloClass;
}());

let hello = new HelloClass('Hello');
hello.sayGreeting();

console.log(hello instanceof HelloClass);
console.log(hello instanceof Object);

console.log(typeof HelloClass);
console.log(typeof HelloClass.prototype.sayGreeting);

類表達式

類表達式能夠是被命名的或匿名的。賦予一個命名類表達式的名稱是類的主體的本地名稱。和function的表達式相似,但不會像函數聲名或和函數表達式同樣被提高。prototype

/* 匿名類 */ 
let Rectangle = class {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
};
console.log(typeof Rectangle); // function
/* 命名的類 */ 
let Rectangle = class Rectangle1 {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
};
console.log(typeof Rectange); // function
console.log(typeof Rectange1); // undefined

在JS中,函數爲一等「公民」,能夠傳入函數,也能夠從函數中返回,還能夠賦值給變量的值。也是JS中的一等公民。code

訪問器

- getter
- setter
class Rectangle {
    // constructor
    constructor(height, width) {
        this.height = height;
        this.width = width;
    }
    // Getter
    get area() {
        return this.calcArea()
    }
    // Method
    calcArea() {
        return this.height * this.width;
    }
}
const square = new Rectangle(10, 10);

console.log(square.area);
// 100

可計算成員

const methodName = "sayGreeting";
class HelloClass {
    constructor(greeting) {
        this.greeting = greeting;
    }
    
    [methodName]() {
        console.log(this.greeting);
    }
}

let hello = new HelloClass('Hello');
hello.sayGreeting(); // Hello
hello[methodName](); // Hello

可計算訪問器屬性。orm

const propertyName = "greeting";
class HelloClass {
    constructor() {
        
    }
    
    get [propertyName]() {
        return this.greetingStr;
    }
    set [propertyName](value) {
        this.greetingStr = value;
    }
}

let hello = new HelloClass();
hello.greeting = 'Hello';
console.log(hello.greeting);

生成器方法

class NormClass {
    *createIterator() {
        yield 1;
        yield 2;
        yield 3;
    }
}
let instance = new NormClass();
let iterator = instance.createIterator();
console.log(iterator.next());  // { value: 1, done: false }
console.log(iterator.next());  // { value: 2, done: false }
console.log(iterator.next());  // { value: 3, done: false }
console.log(iterator.next());  // { value: undefined, done: true }

爲類定義默認迭代器。htm

class Collection {
    constructor() {
        this.items = [];
    }

    *[Symbol.iterator]() {
        yield *this.items.values();
    }
}

var coll = new Collection();
coll.items.push(1);
coll.items.push(2);
coll.items.push(3);
for (let i of coll) {
    console.log(i);
}
// 1
// 2
// 3

靜態成員

class Animal { 
    speak() {
      return this;
    }
    static eat() {
      return this;
    }
  }
  
  let obj = new Animal();
  console.log(obj.speak()); // Animal {}
  let speak = obj.speak;
  console.log(speak()); // undefined
  
  console.log(Animal.eat()); // class Animal
  let eat = Animal.eat;
  console.log(eat()); // undefined
相關文章
相關標籤/搜索