ES6 - Note4:Class類

来源:http://www.cnblogs.com/zmxmumu/archive/2016/06/16/5588431.html
-Advertisement-
Play Games

1.Class類的介紹 在ES6中新增了Class類的概念,讓語法看起來更像是面向對象編程,其實這可以說是一個語法糖,ES5可以做到Class絕大部分功能,但也有一些不同。在ES6以前,可以通過構造函數來模擬類的概念,如下所示 在引入了Class關鍵字後,可以這樣做,如下所示 如上所示,便是ES6中 ...


1.Class類的介紹

在ES6中新增了Class類的概念,讓語法看起來更像是面向對象編程,其實這可以說是一個語法糖,ES5可以做到Class絕大部分功能,但也有一些不同。在ES6以前,可以通過構造函數來模擬類的概念,如下所示

function Student(name,age){
	this.name = name;
	this.age  = age;
}
Student.prototype = {
	constructor:Student,
	show:function(){
		console.log(this.name,this.age);
	}
};
var xiaoming = new Student("xiaoming",20);
xiaoming.show();
xiaoming 20

在引入了Class關鍵字後,可以這樣做,如下所示

class Person{
	constructor(name,age){ //構造函數,預設返回this對象,如果強制返回其他對象也是被允許的
		this.name = name;
		this.age  = age;
	}
	show(){
		console.log(this.name,this.age);
	}
}
var s = new Person('test',30);
s.show();
test 30

如上所示,便是ES6中類的定義,上面的constructor函數是類的構造函數,如果不寫,則會自動創建一個constructor空構造函數,並且方法之間不允許有逗號,否則會報錯,如下所示

class Person{
	show(){
		alert("show");
	},
	hide(){
		alert("hide");
	}
}
var s = new Person();
s.show();
SyntaxError: invalid property id

其實類的數據類型就是函數,類本身就指向構造函數,如下所示

class Person{
	constructor(name,age){
		this.name = name;
		this.age  = age;
	}
	show(){
		console.log(this.name,this.age);
	}
}
typeof Person
"function"
Person.prototype.constructor===Person
true
var p = new Person('test',20);
undefined
p.constructor
function Person()
p.constructor == Person
true

prototype屬性在類上依舊存在,且類的方法都定義在類的prototype上面,如下所示

var person = new Person('person',100);
person.constructor === Person.prototype.constructor
true

因此可以在類的prototype上面定義的新方法為類擴展方法,如下所示

Object.assign(Person.prototype,{show(){console.log(this.name);}});
person.show();
var a = new Person('nihao',20);
a.show();

person
nihao

但是類內部定義的方法是不可枚舉的,這和ES5的構造函數還是有很大的區別,如下所示

Object.getOwnPropertyNames(Person.prototype)
Array [ "constructor", "show" ]
Object.keys(Person.prototype)
Array [  ]

類的屬性名可以使用表達式來定義,如下所示

var show = 'show';
class Test{
	constructor(){
		console.log("class test constructing...");
	}
	[show](){
		console.log('show');
	}
}
var test = new Test();
test[show]();
class test constructing...
show

在生成類的實例對象時,必須使用new關鍵字,如果直接像調用函數那樣調用類,則會報錯,如下所示

var t1 = Test();
TypeError: class constructors must be invoked with |new|

類的所有實例共用一個原型,實例對象可以通過__proto__屬性來訪問原型,因此可以通過該屬性為原型添加方法,如下所示

test.__proto__.say = () => "hello prototype!";
test.say();
new Test().say();
class test constructing...
"hello prototype!"
test.say()

類Class也可以像Function一樣,採用表達式形式來定義,如下所示

var Aclass = class Bclass{
    constructor(){
        console.log(Bclass.name);//只有在類的內部才能訪問到Bclass
    }
    show(){
        console.log('Aclass...');
    }
};
var a = new Aclass();
a.show();
Bclass
Aclass...

因此我們可以寫出類似立執行函數的立執行類,如下所示

var iifeInstance = new class{
    constructor(text){
        this.text = text;
    }
    show(){
        console.log(this.text);
    }
}('iife testing...');
iifeInstance.show();
iife testing...

類的定義不存在變數聲明提升,這和ES5函數不同,如下圖所示

var a = new Dclass();
class Dclass{
    
}
ReferenceError: can't access lexical declaration `Dclass' before initialization

2.Class類的繼承

Class類的繼承通過關鍵字extends來實現,和ES5通過修改原型鏈實現繼承不同,如下所示

class Person{
    constructor(name,age){
        this.name = name;
        this.age  = age;
    }
    print(){
        console.log(this.name,this.age);
    }
}
class Student extends Person{
    constructor(name,age,sno){
        super(name,age); //調用父類的構造函數,必須存在且需放在子類使用this對象之前,否則將報錯
        this.sno = sno;
    }
    print(){
        super.print();
        console.log(this.sno);
    }
}
var s = new Student('xiaoming',20,"21014130217");
s.print();
xiaoming 20
21014130217

值得註意的是在定義子類構造函數時,一定要調用父類的構造函數且必須在子類使用this對象之前,因為子類不存在this對象,需要使用super得到父類的this對象,然後對其進行改寫加工。如果預設構造函數,則會自動創建一個預設的構造函數並調用父類的構造函數

子類的原型prototype是父類的實例,有點像原型鏈繼承,子類__proto__指向父類,這和函數的預設繼承不同。如下所示

Student.prototype instanceof Person
true
Student.prototype.__proto__ === Person.prototype
true
s.__proto__ === Student.prototype
true
Student.__proto__ === Person
true

可以使用Object.getPrototypeOf獲取子類的父類,如下所示

Object.getPrototypeOf(Student) === Person
true

3.原生構造函數的繼承

在ES5中不能繼承原生的構造函數,例如Array,Date,Object,Function等等,但是在ES6中可以實現對原生構造函數的繼承,如下所示

class MyArray extends Array{
    constructor(){
        super();
        this.sign = "myArray";
    }
}
var myArr = new MyArray();
console.log(myArr);
myArr.push(1,2,3);
console.log(myArr);
Array [  ]
Array [ 1, 2, 3 ]
console.log(myArr.sign);
"myArray"

但是在繼承Object時,有一點差異就是調用super給Object構造函數傳參時會被忽略,這是ES6在實現時檢測到不是以new Object形式調用構造函數,則忽略參數,如下所示

class MyObj extends Object{
    constructor(arg){
        super(arg);
        this.sign = "MyObj";
    }
}
var myObj = new MyObj({x:1});
console.log(myObj.x);
undefined

3.類的getter和setter函數,與ES5中的一樣,都是對類屬性存取行為的攔截,如下所示

class Xclass{
    constructor(){
        console.log('Xclass initializing...');
    }
    set x(val){
        console.log(val);
    }
    get x(){
        return 2;
    }
}

var xIns = new Xclass();
xIns.x = 4;
console.log(xIns.x);
Xclass initializing...
4
2

4.類的靜態方法與靜態屬性

靜態方法與屬性不能被實例對象調用,靜態方法可以在類內部定義,但靜態屬性則不能,靜態方法可以被子類繼承,如下所示

class StaticTest{
    static test(){
        console.log('static...');
    }
}
class SubStatic extends StaticTest{
    show(){
        console.log('substatic show...');
    }
}
StaticTest.test();
SubStatic.test();
new SubStatic().show();
new StaticTest().test();
static...  2次
substatic show...
TypeError: (intermediate value).test is not a function

 靜態屬性的定義則是直接使用ClassName.prop形式來定義,如下所示

class StaticTest{
    static test(){
        console.log('static...');
    }
}
StaticTest.xxx = "hello class static variable";
StaticTest.xxx;
"hello class static variable"

5.new.target

在ES6中為new命令添加了一個target屬性,該屬性在構造函數中返回new命令作用於的那個函數,如果不是以new命令調用構造函數則返回undefined,如下所示

class Target{
    constructor(){
        console.log(Object.is(new.target,Target));
    }
}
var target = new Target();
true

有了這個屬性,我們可以強制構造函數必須以new命令實例化,如下所示

function Animal(name){
    if(!new.target) throw new Error('必須使用new實例化Animal');
    this.name = name;
}
var duck1 = new Animal('duck1');
console.log(duck1.name);
var duck2 = Animal('duck2');
duck1
Error: 必須使用new實例化Animal

也可以用來模仿抽象類,不能被實例化,只能被繼承使用

class Car{
    constructor(brand){
        if(new.target === Car) throw new Error('Car類不能被實例化');
        this.brand = brand;
    }
}
class Baoma extends Car{
    constructor(brand){
        super(brand);
    }
    showBrand(){
        console.log(this.brand);
    }
}
var baoma = new Baoma('baoma');
baoma.showBrand();
baoma
var car = new Car('car');
Error: Car類不能被實例化

在實例化子類時,父類的new.target指向的是子類。

 

 

  

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • JS格式化金額,正則方式修改。 ...
  • 實現tab切換的主要html代碼: 實現tab切換的jquery代碼: ...
  • 在之前項目後臺管理界面開發中,不知道有layer這樣好用的組件,我的內心是這樣的的。。。呀!這個框架有彈框,哈哈哈,好開心,不用自己寫遮罩層,不用自己寫彈框,好開森。。 當知道有layer之後。。。。。這麼方便,這麼人性化,好漂亮,哇哦,好簡單。。。 或許我這人看到新鮮的東西都叫好吧,不好的暫時沒發 ...
  • [1]一元加 [2]一元減 [3]遞增 [4]遞減 [5]加法 [6]減法 [7]乘法 [8]除法 [9]求餘 ...
  • 我們知道,JavaScript中檢測對象類型的運算符有:typeof、instanceof,還有對象的constructor屬性: 1) typeof 運算符 typeof 是一元運算符,返回結果是一個說明運算數類型的字元串。如:"number","string","boolean","object ...
  • div+css3實現漂亮的多動畫彩標簽雲,滑鼠移動會有動畫 點擊運行效果 ...
  • 因為我是前端剛入門,昨天看了一個大神寫的的初級前端需要掌握的知識,然後我就開始一一搜索,下麵是我對css預處理器和後處理器的搜索結果,一是和大家分享下這方面的知識,另一方面方便自己以後翻閱。所以感興趣的可以看下。 轉載自"趙雷的博客",原文地址:http://zhaolei.info/2014/01 ...
  • 今天要跟大家談的是事件冒泡,這個事件呢,也是兩面性的,有時候給我們帶來bug,有時候優點也很明顯。我們就一起來看看它的真面目。 首先看看事件冒泡是什麼? 事件冒泡 :當一個元素接收到事件的時候 會把他接收到的事件傳給自己的父級,一直到window 。(註意這裡傳遞的僅僅是事件 並不傳遞所綁定的事件函 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...