前言
隨着ES6標准的定稿,眾多的特性也趨於穩定,各大瀏覽器也在逐步實現這些特性,那么對ES6有更多的了解就無可厚非了。
准備
在學習ES6之前,我們需要有一個環境來測試ES6代碼。在這里我推薦使用node的分支io.js。
-
如何安裝?
- 下載地址:https://iojs.org/en/index.html,如果各位小伙伴不習慣英文,可以把url中的en修改為cn。
- 然后根據自己的操作系統版本,下載合適的安裝包(主要指Windows系統)進行安裝。
- 安裝過程就不一一贅述了,和一般軟件一樣。
-
如何驗證安裝成功?
- 打開cmd,然后輸入
iojs -v
,如果輸出一個版本號,那么就代表io.js安裝成功。(PS:我現在使用的是v1.2.0) - 也可以輸入
iojs -p process.versions.v8
查看iojs所使用的V8(PS:不是V8發動機)的版本。(PS:我這兒顯示4.1.0.14)
- 打開cmd,然后輸入
小窺ES6
在測試ES6代碼前,我們可以先看下io.js對ES6的支持:https://iojs.org/cn/es6.html。
接下來,開始我們的ES6-Class之旅:
1、class 基礎
大家應該知道,在大部分面向對象的語言中,都有class的說法,那么在早期的Js中,面向對象的實現比較特殊,我們必須要用function來模擬。如:
//ES5及以下
function Point(x, y){
this.x = x;
this.y = y;
}
var p1 = new Point(100, 100);
然而在ES6中,我們可以直接使用class關鍵字,如:
//ES6
'use strict' //不能去掉,要不然iojs會提示不認識class。
class Point{
constructor(x, y){
this.x = x;
this.y = y;
}
}
var p1 = new Point(100, 100);
console.log(p1);
將以上代碼保存為1.js,那么執行如下命令:iojs --es_staging 1.js
就可以看到"{x:100, y: 100}"這個結果了。(PS:注意要在1.js的目錄打開cmd)。
接下來,看一個復雜點的,繼承:
//ES6
'use strict'
class Point{
constructor(x, y){
this.x = x;
this.y = y;
}
}
var p1 = new Point(100, 100);
console.log(p1);
class ColorPoint extends Point{
constructor(x, y, color){
super(x, y);
this.color = color;
}
}
var cp = new ColorPoint(50, 50, 'red');
console.log(cp);
//輸出繼承關系
console.log(cp instanceof ColorPoint); //true
console.log(cp instanceof Point); //true
可以看到,和大部分語言的繼承都很類似,如果你有其他面向對象語言的基礎,那么很容易就能理解。
對Point和ColorPoint進行typeof,結果很明顯也能看到是function。
console.log(typeof Point); // function
console.log(typeof ColorPoint); // function
那如果對class進行函數調用呢?
Point(100, 100); //Error
如上,必須通過new調用class,直接使用函數調用則會報錯。
再來對比以下代碼:
//標准的函數可以先寫調用語句,后寫申明語句。因為會定義前置
foo();
function foo(){}
//如果是class呢?
new Foo(); //Error,Foo is not defined
class Foo{}
如上,如果是定義的class,那么必須要定義語句在前,調用在后。
再來看以下的情形:
function funThatUseBar(){
new Bar();
}
//funThatUseBar(); //Error,Bar is not defined
class Bar{}
funThatUseBar(); //ok
如上,如果先使用了Bar,那么也是會報錯的。必須要優先定義class。
附上以上所有的js,會報錯的語句,進行了注釋。
//ES6
'use strict'
class Point{
constructor(x, y){
this.x = x;
this.y = y;
}
}
var p1 = new Point(100, 100);
console.log(p1);
class ColorPoint extends Point{
constructor(x, y, color){
super(x, y);
this.color = color;
}
}
var cp = new ColorPoint(50, 50, 'red');
console.log(cp);
//*********************************************
//輸出繼承關系
console.log(cp instanceof ColorPoint); //true
console.log(cp instanceof Point); //true
console.log(typeof Point); // function
console.log(typeof ColorPoint); // function
//Point(100, 100); //Error
//************************************
//標准的函數可以先寫調用語句,后寫申明語句。因為會定義前置
foo();
function foo(){}
//如果是class呢?
//new Foo(); //Error,Foo is not defined
class Foo{}
//*******************************************
function funThatUseBar(){
new Bar();
}
//funThatUseBar(); //Error,Bar is not defined
class Bar{}
funThatUseBar(); //ok
2、類中的主體
ES6中、class的主體只能包含方法,不能包含數據屬性。如果在類中包含變量定義,則會報錯。class中的方法有三種類型:構造函數、靜態方法、原型方法,如:
class Class1{
//構造
constructor(options){
}
// 靜態方法,靜態方法用static修飾
static staticMethod(){
return 'static method';
}
prototypeMethod(){
return 'prototype method';
}
}
其中,每個class和class原型的constructor都是相等的,同時class本質也是function
console.log(Class1 === Class1.prototype.constructor) // true
console.log(typeof Class1) // function
然后我們對類中的方法做測試
var p = console.log;
p(typeof Class1.prototype.prototypeMethod);
Class1.prototype.prototypeMethod() // 原型方法調用方式
p(typeof Class1.staticMethod);
Class1.staticMethod() //靜態方法調用方式
Getters 和 Setters 的用法
class Class2{
get name(){
return 'jay';
}
set name(value){
console.log('set name = ' + value);
}
}
var c2 = new Class2();
c2.name = 'hu'; // "set name = hu"
console.log(c2.name); // "jay"
當使用了get和set時,那么針對屬性的get和set會自動調用class中相關的方法。
貼出所有Js代碼:
'use strict'
class Class1{
//構造
constructor(options){
}
// 靜態方法
static staticMethod(){
return 'static method';
}
prototypeMethod(){
return 'prototype method';
}
}
console.log(Class1 === Class1.prototype.constructor);
console.log(typeof Class1);
var p = console.log;
p(typeof Class1.prototype.prototypeMethod);
p(typeof Class1.staticMethod);
class Class2{
get name(){
return 'jay';
}
set name(value){
console.log('set name = ' + value);
}
}
var c2 = new Class2();
c2.name = 'hu';
console.log(c2.name);
3、類的繼承
簡單的繼承關系,如下:
'use strict'
class Class1{
toString(){
return 'parent class.';
}
}
class SubClass extends Class1{
toString(){
return 'sub class.';
}
}
var sc = new SubClass();
console.log(sc.toString()); // "sub class"
其中,sc是Class1的實例,也是SubClass的實例:
console.log(sc instanceof Class1); //true
console.log(sc instanceof SubClass); //true
如果要調用父類的方法,怎么辦呢?
class SubClass2 extends Class1{
toString(){
return super.toString();
}
}
var sc2 = new SubClass2();
console.log(sc2.toString());
在繼承關系中,子類的原型等於父類:
console.log(Object.getPrototypeOf(SubClass2) === Class1); //true
在子類中訪問父類構造,使用super即可。
其他
- 如果想一覽所有的ES6新特性,可以參考https://github.com/lukehoban/es6features
- 如果想系統的學習ES6,那么推薦http://es6.ruanyifeng.com/
- 想了解更多Classes in ECMAScript 6,可參考http://www.2ality.com/2015/02/es6-classes-final.html