Class
學過Java的小伙伴會發(fā)現(xiàn), 這個class和Java里的class基本語法并沒有什么區(qū)別... 下面正式開始介紹.
定義類
JavaScript 語言的傳統(tǒng)方法是通過構造函數(shù)昔榴,定義并生成新對象歉糜。
//例:
function Point (x,y) {
this.x = x;
this.y = y;
}
Point.prototype.toString = function () {
return '(' + this.x + ', ' + this.y + ')';
}
var oP = new Point(1,2);
console.log(oP);
ES6提供了更接近傳統(tǒng)語言的寫法丧荐,引入了Class(類)這個概念莫绣,
作為對象的模板。通過class關鍵字诗鸭,可以定義類染簇。
基本上,ES6的class可以看作只是一個語法糖强岸,它的絕大部分功能锻弓,ES5都可以做到,
新的class寫法只是讓對象原型的寫法更加清晰蝌箍、更像面向?qū)ο缶幊痰恼Z法而已青灼。
上面的代碼用ES6的“類”改寫,就是下面這樣妓盲。
class Point {
constructor(x,y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' +this.y + ')';
}
}
var oP = new Point(1,2);
console.log(oP);
console.log(oP.toString());
需要注意一下幾個小問題:
**1. **代碼定義了一個“類”杂拨,可以看到里面有一個constructor方法,這就是構造方法悯衬,而this關鍵字則代表實例對象弹沽。
**2. **注意,定義“類”的方法的時候筋粗,前面不需要加上function這個保留字策橘,直接把函數(shù)定義放進去了就可以了。
**3. **另外娜亿,方法之間不需要逗號分隔丽已,加了會報錯。
**4. **類的數(shù)據(jù)類型就是函數(shù)买决,類本身就指向構造函數(shù)
**5. **構造函數(shù)的prototype屬性促脉,在ES6的“類”上面繼續(xù)存在。
事實上策州,類的所有方法都定義在類的prototype屬性上面。
class Point {
constructor() {
this.x = 10;
alert(0);
}
toString() {
alert('1');
}
toValue() {
alert('2');
}
}
console.log(Point.prototype);
**6. **類的內(nèi)部所有定義的方法宫仗,都是不可枚舉的(enumerable)够挂。
//例
class Point {
constructor (x,y) {
console.log(x,y);
}
toString() {
console.log(1);
}
}
function Point1 () {
this.toString = function () {
console.log(1);
}
}
Point1.prototype.toValue = function () {
console.log(2);
}
var oP = new Point(1,2);
var oP1 = new Point1();
for (var name in oP) {
console.log(name);// 1 2
}
for (var name in oP1) {
console.log(name);// toString toValue
}
**7. **類的實例共享一個原型對象
class Point {
}
var p1 = new Point();
Point.prototype.say = function () {console.log('YyYy')};
var p2 = new Point();
// 實例的__proto__ 指向構造函數(shù)的prototype;
p1.__proto__.printName = function () { console.log('OoOo')};
var p3 = new Point();
p1.printName();//OoOo
p2.printName();//OoOo
p3.printName();//OoOo
p1.say();//YyYy
p2.say();//YyYy
p3.say();//YyYy
繼承(單繼承)
跟java沒啥區(qū)別, 但同ES5是有一個區(qū)別的; 先看一個繼承實例.
//例:
class Father {
constructor(){
this.house = 2;
}
}
class Child extends Father{
constructor(){
super();
this.age = 10;
}
}
子類必須在constructor方法中調(diào)用super方法,否則新建實例時會報錯藕夫。這是因為子類沒有自己的this對象孽糖,而是繼承父類的this對象枯冈,然后對其進行加工。如果不調(diào)用super方法办悟,子類就得不到this對象尘奏。
ES5的繼承,實質(zhì)是先創(chuàng)造子類的實例對象this病蛉,然后再將父類的方法添加到this上面(Parent.apply(this))炫加。ES6的繼承機制完全不同,
實質(zhì)是先創(chuàng)造父類的實例對象this(所以必須先調(diào)用super方法)铺然,然后再用子類的構造函數(shù)修改this俗孝。
Class 靜態(tài)方法
定義: 類相當于實例的原型,所有在類中定義的方法魄健,都會被實例繼承赋铝。如果在一個方法前,加上static關鍵字沽瘦,就表示該方法不會被實例繼承革骨,而是直接通過類來調(diào)用,這就稱為“靜態(tài)方法”析恋。
// Foo類的classMethod方法前有static關鍵字良哲,表明該方法是一個靜態(tài)方法,
// 可以直接在Foo類上調(diào)用(Foo.classMethod())绿满,而不是在Foo類的實例上調(diào)用臂外。
// 如果在實例上調(diào)用靜態(tài)方法,會拋出一個錯誤喇颁,表示不存在該方法漏健。
//例1
class Foo {
static classMethod() {
console.log('hello');
}
}
Foo.classMethod() // 'hello'
var foo = new Foo();
foo.classMethod();//報錯: foo.classMethod is not a function
//父類的靜態(tài)方法,可以被子類繼承
class Bar extends Foo {
}
Bar.classMethod();//hello
//例2:
// 靜態(tài)方法也可以從super對象上調(diào)用
class Foo2 {
static classMethod() {
return 'Foo2 staic';
}
}
class Bar2 extends Foo2 {
constructor () {
super();
}
static classMethod() {
console.log(super.classMethod() + ', too');
}
say() {
console.log(super.classMethod() + ', say');//報錯 :(intermediate value).classMethod is not a function
}
}
// 子類調(diào)用父類的static方法只能在靜態(tài)函數(shù)中調(diào)用
var oB2 = new Bar2();
oB2.say();
Bar2.classMethod();