Class 類

class聲明

class 是 ES6 模仿面向?qū)ο笳Z言(C++, Java)提出的定義類的方法。形式類似 C++ 和 Java (各取所長), 下面例子展示了 class 是如何定義構(gòu)造函數(shù)偶惠、對象屬性和對象動/靜態(tài)方法的:

class Point{
  constructor(x, y){    //定義構(gòu)造函數(shù)
    this.x = x;         //定義屬性x
    this.y = y;         //定義屬性y
  }                     //這里沒有逗號
  toString(){           //定義動態(tài)方法柄冲,不需要 function 關(guān)鍵字
    return `(${this.x},${this.y})`;
  }
  static show(){        //利用 static 關(guān)鍵字定義靜態(tài)方法
    console.log("Static function!");
  }
}

var p = new Point(1,4);
console.log(p+"");               //(1,4)
console.log(typeof Point);       //"function"
console.log(Point.prototype.constructor === Point);    //true
console.log(Point.prototype.constructor === p.constructor);    //true
Point.show();      //"Static function!"

相當(dāng)于傳統(tǒng)寫法:

function Point(x, y){
  this.x = x;
  this.y = y;
}
Point.prototype.toString = function(){
  return `(${this.x},${this.y})`;
}
Point.show = function(){
  console.log("Static function!");
}
var p = new Point(1,4);
console.log(p+"");   //(1,4)

這里不難看出舶吗,class 的類名就是 ES5 中的構(gòu)造函數(shù)名帽芽,靜態(tài)方法就定義在其上扛邑,而類的本質(zhì)依然是個函數(shù)。而 class 中除了 constructor 是定義的構(gòu)造函數(shù)以外闷煤,其他的方法都定義在類的 prototype 上,這都和 ES5 是一致的涮瞻,這就意味著鲤拿,ES5 中原有的那些方法都可以用, 包括但不限于:

  • Object.keys(), Object.assign() 等等
  • 而且 class 也同樣支持表達(dá)式做屬性名,比如 Symbol
  • ES5 函數(shù)具有的屬性/方法:length署咽、name近顷、apply生音、call、bind窒升、arguments 等等

但有些細(xì)節(jié)還是有區(qū)別的缀遍,比如:

class Point{
  constructor(x, y){    //定義構(gòu)造函數(shù)
    this.x = x;         //定義屬性x
    this.y = y;         //定義屬性y
  }                     //這里沒有逗號
  toString(){           //定義動態(tài)方法,不需要 function 關(guān)鍵字
    return `(${this.x},${this.y})`;
  }
  getX(){
    return this.x;
  }
  getY(){
    return this.y;
  }
}
var p = new Point(1,4);
var keys = Object.keys(Point.prototype);
var ownKeys = Object.getOwnPropertyNames(Point.prototype);
console.log(keys);        //[]
console.log(ownKeys);     //["constructor", "toString", "getX", "getY"]
console.log(p.hasOwnProperty("toString"));                  //false
console.log(p.__proto__.hasOwnProperty("toString"));        //true
//ES5
function Point(x, y){
  this.x = x;
  this.y = y;
}
Point.prototype = {
  toString(){
    return '(' + this.x + ',' + this.y + ')';
  },
  getX(){
    return this.x;
  },
  getY(){
    return this.y;
  }
}
var p = new Point(1,4);
var keys = Object.keys(Point.prototype);
var ownKeys = Object.getOwnPropertyNames(Point.prototype);
console.log(keys);        //["toString", "getX", "getY"]
console.log(ownKeys);     //["toString", "getX", "getY"]
console.log(p.hasOwnProperty("toString"));                  //false
console.log(p.__proto__.hasOwnProperty("toString"));        //true

這個例子說明饱须,class 中定義的動態(tài)方法是不可枚舉的域醇,并且 constructor 也是其自有方法中的一個。

使用 class 注意一下幾點:

  • class 中默認(rèn)是嚴(yán)格模式冤寿,即使不寫"use strict歹苦。關(guān)于嚴(yán)格模式可以看:嚴(yán)格模式特點
  • 同名 class 不可重復(fù)聲明
  • class 相當(dāng)于 object 而不是 map,不具有 map 屬性督怜,也不具有默認(rèn)的 Iterator殴瘦。
  • constructor 方法在 class 中是必須的,如果沒有認(rèn)為指定号杠,系統(tǒng)會默認(rèn)生成一個空的 constructor
  • 調(diào)用 class 定義的類必須有 new 關(guān)鍵字蚪腋,像普通函數(shù)那樣調(diào)用會報錯。ES5 不限制這一點姨蟋。
TypeError: Class constructor Point cannot be invoked without 'new'
  • constructor 方法默認(rèn)返回值為 this屉凯,可以認(rèn)為修改返回其他的值,但這會導(dǎo)致一系列奇怪的問題:
class Point{
  constructor(x,y){
    return [x, y];
  }
}
new Point() instanceof Point;    //false
  • class 聲明類不存在變量提升
new Point();     //ReferenceError: Point is not defined
class Point{}

class 表達(dá)式

這個和面向?qū)ο蟛灰粯恿搜廴埽琷s 中函數(shù)可以有函數(shù)聲明形式和函數(shù)表達(dá)式2種方式定義悠砚,那么 class 一樣有第二種2種定義方式:class 表達(dá)式

var className1 = class innerName{
  //...
};
let className2 = class innerName{
  //...
};
const className3 = class innerName{
  //...
};

class 表達(dá)式由很多特性和 ES5 一樣:

  • 和函數(shù)表達(dá)式類似,這里的innerName可以省略堂飞,而且innerName只有類內(nèi)部可見灌旧,實際的類名是賦值號前面的 className。
  • 這樣定義的類的作用域绰筛,由其所在位置和聲明關(guān)鍵字(var, let, const)決定
  • const申明的類是個常量枢泰,不能修改。
  • 其變量聲明存在提升铝噩,但初始化不提升
  • class 表達(dá)式也不能和 class 申明重名

ES5 中有立即執(zhí)行函數(shù)衡蚂,類似的,這里也有立即執(zhí)行類:

var p = new class {
  constructor(x, y){
    this.x = x;
    this.y = y;
  }
  toString(){
    return `(${this.x},${this.y})`;
  }
}(1,5);   //立即生成一個對象
console.log(p+"");    //(1,5)

getter, setter 和 Generator 方法

getter 和 setter 使用方式和 ES5 一樣, 這里不多說了骏庸,舉個例子一看就懂:

class Person{
  constructor(name, age, tel){
    this.name = name;
    this.age = age;
    this.tel = tel;
    this._self = {};
  }
  get id(){
    return this._self.id;
  }
  set id(str){
    if(this._self.id){
      throw new TypeError("Id is read-only");
    } else {
      this._self.id = str;
    }
  }
}
var p = new Person("Bob", 18, "13211223344");
console.log(p.id);                //undefined
p.id = '30010219900101009X';
console.log(p.id);                //'30010219900101009X'

var descriptor = Object.getOwnPropertyDescriptor(Person.prototype, 'id');
console.log('set' in descriptor);       //true
console.log('get' in descriptor);       //true

p.id = '110';                     //TypeError: Id is read-only

Generator 用法也和 ES6 Generator 部分一樣:

class Person{
  constructor(name, age, tel){
    this.name = name;
    this.age = age;
    this.tel = tel;
    this._self = {};
  }
  *[Symbol.iterator](){
    var keys = Object.keys(this);
    keys = keys.filter(function(item){
      if(/^_/.test(item)) return false;
      else return true;
    });
    for(let item of keys){
      yield this[item];
    }
  }
  get id(){
    return this._self.id;
  }
  set id(str){
    if(this._self.id){
      throw new TypeError("Id is read-only");
    } else {
      this._self.id = str;
    }
  }
}
var p = new Person("Bob", 18, "13211223344");
p.id = '30010219900101009X';
for(let info of p){
  console.log(info);   //依次輸出: "Bob", 18, "13211223344"
}

class 的繼承

這里我們只重點講繼承毛甲,關(guān)于多態(tài)沒有新的修改,和 ES5 中一樣敞恋,在函數(shù)內(nèi)判斷參數(shù)即可丽啡。關(guān)于多態(tài)可以閱讀對象、類與原型鏈中關(guān)于多態(tài)重構(gòu)的部分硬猫。

此外补箍,class 繼承屬于 ES5 中多種繼承方式的實例繼承改执,關(guān)于共享原型也在上面這篇文章中講解過。

class 實現(xiàn)繼承可以簡單的通過 extends 關(guān)鍵字實現(xiàn), 而使用 super 關(guān)鍵字調(diào)用父類方法:

//定義 '有色點'' 繼承自 '點'
class ColorPoint extends Point{    //這里延用了上面定義的 Point 類
  constructor(x, y, color){
    super(x, y);     //利用 super 函數(shù)調(diào)用父類的構(gòu)造函數(shù)
    this.color = color;
  }
  toString(){
    return `${super.toString()},${this.color}`;     //利用 super 調(diào)用父類的動態(tài)方法
  }
}
var cp = new ColorPoint(1, 5, '#ff0000');
console.log(cp+"");      //(1,5),#ff0000
ColorPoint.show();       //"Static function!"     靜態(tài)方法同樣被繼承了
cp instanceof ColorPoint;   //true
cp instanceof Point;   //true

使用 extends 繼承的時候需要注意一下幾點:

  • super 不能單獨使用坑雅,不能訪問父類屬性辈挂,只能方法父類方法和構(gòu)造函數(shù)(super本身)
  • 子類沒有自己的 this,需要借助 super 調(diào)用父類構(gòu)造函數(shù)后加工得到從父類得到的 this裹粤,子類構(gòu)造函數(shù)必須調(diào)用 super 函數(shù)终蒂。這一點和 ES5 完全不同。
  • 子類如果沒有手動定義構(gòu)造函數(shù)遥诉,會自動生成一個構(gòu)造函數(shù)拇泣,如下:
constructor(...args){
  super(...args);
}
  • 子類中使用 this 關(guān)鍵字之前,必須先調(diào)用 super 構(gòu)造函數(shù)
  • 由于繼承屬于共享原型的方式矮锈,所以不要在實例對象上修改原型(Object.setPrototypeOf, obj.__proto__等)
  • super 也可以用在普通是對象字面量中:
var obj = {
  toString(){
    return `MyObj ${super.toString()}`;
  }
}
console.log(obj+"");    //MyObj [object Object]

prototype__proto__

在 class 的繼承中

  • 子類的 __proto__ 指向其父類
  • 子類 prototype 的 __proto__ 指向其父類的 prototype
class Point{
  constructor(x, y){
    this.x = x;
    this.y = y;
  }
}
class ColorPoint extends Point{
  constructor(x, y, color){
    super(x, y);
    this.color = color;
  }
}
ColorPoint.__proto__  === Point;   //true
ColorPoint.prototype.__proto__ === Point.prototype;   //true

其等價的 ES5 是這樣的:

function Point(){
  this.x = x;
  this.y = y;
}
function ColorPoint(){
  this.x = x;
  this.y = y;
  this.color = color;
}
Object.setPrototypeOf(ColorPoint.prototype, Point.prototype);    //繼承動態(tài)方法屬性
Object.setPrototypeOf(ColorPoint, Point);                        //繼承靜態(tài)方法屬性

ColorPoint.__proto__  === Point;                      //true
ColorPoint.prototype.__proto__ === Point.prototype;   //true

這里我們應(yīng)該理解一下3種繼承的 prototype 和 __proto__

  1. 沒有繼承

class A{}
A.__proto__  === Function.prototype;          //true
A.prototype.__proto__ === Object.prototype;   //true
  1. 繼承自 Object
class A extends Object{}
A.__proto__  === Object;                      //true
A.prototype.__proto__ === Object.prototype;   //true
  1. 繼承自 null
class A extends null{}
A.__proto__  === Function.prototype;        //true
A.prototype.__proto__ === undefined;        //true

判斷類的繼承關(guān)系:

class A{}
class B extends A{}
Object.getPrototypeOf(B) === A;     //true

子類的實例的 __proto____proto__ 指向其父類實例的 __proto__

class A{}
class B extends A{}
var a = new A();
var b = new B();
B.__proto__.__proto__ === A.__proto__;        //true

因此霉翔,可以通過修改子類實例的 __proto__.__proto__ 改變父類實例的行為。建議:

  • 總是用 class 取代需要 prototype 的操作苞笨。因為 class 的寫法更簡潔债朵,更易于理解。
  • 使用 extends 實現(xiàn)繼承瀑凝,因為這樣更簡單序芦,不會有破壞 instanceof 運算的危險。

此外存取器和 Generator 函數(shù)都可以很理想的被繼承:

class Person{
  constructor(name, age, tel){
    this.name = name;
    this.age = age;
    this.tel = tel;
    this._self = {};
  }
  *[Symbol.iterator](){
    var keys = Object.keys(this);
    keys = keys.filter(function(item){
      if(/^_/.test(item)) return false;
      else return true;
    });
    for(let item of keys){
      yield this[item];
    }
  }
  get id(){
    return this._self.id;
  }
  set id(str){
    if(this._self.id){
      throw new TypeError("Id is read-only");
    } else {
      this._self.id = str;
    }
  }
}

class Coder extends Person{
  constructor(name, age, tel, lang){
    super(name, age, tel);
    this.lang = lang;
  }
}

var c = new Coder("Bob", 18, "13211223344", "javascript");
c.id = '30010219900101009X';
for(let info of c){
  console.log(info);   //依次輸出: "Bob", 18, "13211223344", "javascript"
}
console.log(c.id);     //'30010219900101009X'
c.id = "110";          //TypeError: Id is read-only

多繼承

多繼承指的是一個新的類繼承自已有的多個類粤咪,JavaScript 沒有提供多繼承的方式谚中,所以我們使用 Mixin 模式手動實現(xiàn):

function mix(...mixins){
  class Mix{}
  for(let mixin of mixins){
    copyProperties(Mix, mixin);                         //繼承靜態(tài)方法屬性
    copyProperties(Mix.prototype, mixin.prototype);     //繼承動態(tài)方法屬性
  }

  return Mix;

  function copyProperties(target, source){
    for(let key of Reflect.ownKeys(source)){
      if(key !== 'constructor' && key !== "prototype" && key !== "name"){
        if(Object(source[key]) === source[key]){
          target[key] = {};
          copyProperties(target[key], source[key]);       //遞歸實現(xiàn)深拷貝
        } else {
          let desc = Object.getOwnPropertyDescriptor(source, key);
          Object.defineProperty(target, key, desc);
        }
      }
    }
  }
}

//使用方法:
class MultiClass extends mix(superClass1, superClass2, /*...*/){
  //...
}

由于 mixin 模式使用了拷貝構(gòu)造,構(gòu)造出的子類的父類是 mix 函數(shù)返回的 class, 因此 prototype 和 __proto__ 與任一 superClass 都沒有直接的聯(lián)系寥枝,instanceof 判斷其屬于 mix 函數(shù)返回類的實例藏杖,同樣和任一 superClass 都沒有關(guān)系÷龆伲可以這么說:我們?yōu)榱藢崿F(xiàn)功能破壞了理論應(yīng)該具有的原型鏈。

原生構(gòu)造函數(shù)繼承

在 ES5 中点寥,原生構(gòu)造函數(shù)是不能繼承的艾疟,包括: Boolean(), Number(), Date(), String(), Object(), Error(), Function(), RegExp()等,比如我們這樣實現(xiàn):

function SubArray(){}
Object.setPrototypeOf(SubArray.prototype, Array.prototype);    //繼承動態(tài)方法
Object.setPrototypeOf(SubArray, Array);                        //繼承靜態(tài)方法

var arr = new SubArray();
arr.push(5);
arr[1] = 10;
console.log(arr.length);     //1  應(yīng)該是2
arr.length = 0;
console.log(arr);            //[0:5,1:10]  應(yīng)該為空

很明顯這已經(jīng)不是那個我們熟悉的數(shù)組了敢辩!我們可以用 class 試試:

class SubArray extends Array{}
var arr = new SubArray();
arr.push(5);
arr[1] = 10;
console.log(arr.length);     //2
arr.length = 0;
console.log(arr);            //[]

還是熟悉的味道蔽莱,對吧!這就和之前提到的繼承差異有關(guān)了戚长,子類沒有自己的 this盗冷,需要借助 super 調(diào)用父類構(gòu)造函數(shù)后加工得到從父類得到的 this,子類構(gòu)造函數(shù)必須調(diào)用 super 函數(shù)同廉。而 ES5 中先生成子類的 this仪糖,然后把父類的 this 中的屬性方法拷貝過來柑司,我們都知道,有的屬性是不可枚舉的锅劝,而有的屬性是 Symbol 名的攒驰,這些屬性不能很好的完成拷貝,就會導(dǎo)致問題故爵,比如 Array 構(gòu)造函數(shù)的內(nèi)部屬性 [[DefineOwnProperty]]玻粪。

利用這個特性,我們可以定義自己的合適的類, 比如一個新的錯誤類:

class ExtendableError extends Error{
  constructor(message){
    super(message);
    this.stack = new Error().stack;
    this.name = this.constructor.name;
  }
}
throw new ExtendableError("test new Error");   //ExtendableError: test new Error

靜態(tài)屬性

為何靜態(tài)屬性需要單獨寫诬垂,而靜態(tài)方法直接簡單帶過劲室。因為這是個兼容性問題,目前 ES6 的靜態(tài)方法用 static 關(guān)鍵字结窘,但是靜態(tài)屬性和 ES5 一樣很洋,需要單獨定義:

class A{}
A.staticProperty = "staticProperty";
console.log(A.staticProperty);      //"staticProperty"

不過 ES7 提出可以在 class 內(nèi)部實現(xiàn)定義,可惜目前不支持晦鞋,但是還好有 babel 支持:

class A{
  static staticProperty = "staticProperty";   //ES7 靜態(tài)屬性
  instanceProperty = 18;                      //ES7 實例屬性
}
console.log(A.staticProperty);                //"staticProperty"
console.log(new A().instanceProperty);        //18

new.target 屬性

new 本來是個關(guān)鍵字蹲缠,但 ES6 給它添加了屬性——target。該屬性只能在構(gòu)造函數(shù)中使用悠垛,用來判斷構(gòu)造函數(shù)是否作為構(gòu)造函數(shù)調(diào)用的, 如果構(gòu)造函數(shù)被 new 調(diào)用返回構(gòu)造函數(shù)本身线定,否則返回 undefined:

function Person(){
  if(new.target){
    console.log("constructor has called");
  } else {
    console.log("function has called");
  }
}

new Person();     //"constructor has called"
Person();         //"function has called"

這樣我們可以實現(xiàn)一個構(gòu)造函數(shù),只能使用 new 調(diào)用:

function Person(name){
  if(new.target === Person){
    this.name = name;
  } else {
    throw new TypeError("constructor must be called by 'new'");
  }
}

new Person('Bob');     //"constructor has called"
Person();              //TypeError: constructor must be called by 'new'
Person.call({});       //TypeError: constructor must be called by 'new'

這里需要注意:父類構(gòu)造函數(shù)中的 new.target 會在調(diào)用子類構(gòu)造函數(shù)時返回子類确买,因此使用了該屬性的類不應(yīng)該被實例化斤讥,只用于繼承,類似于 C++ 中的抽象類湾趾。

class Person{
  constructor(name){
    if(new.target === Person){
      this.name = name;
    } else {
      throw new TypeError("constructor must be called by 'new'");
    }
  }
}
class Coder extends Person{}
new Coder('Bob');     //TypeError: constructor must be called by 'new' 這不是我們想要的
//抽象類實現(xiàn)
class Person{
  constructor(name){
    if(new.target === Person){
      throw new TypeError("This class cannot be instantiated");
    }
    this.name = name;
  }
}
class Coder extends Person{}
var c = new Coder('Bob');
console.log(c.name);   //'Bob'
new Person('Bob');     //TypeError: This class cannot be instantiated

關(guān)于抽象類這里解釋一下芭商,要一個類不能實例化只能繼承用什么用?

在繼承中產(chǎn)生歧義的原因有可能是繼承類繼承了基類多次搀缠,從而產(chǎn)生了多個拷貝铛楣,即不止一次的通過多個路徑繼承類在內(nèi)存中創(chuàng)建了基類成員的多份拷貝。抽象類的基本原則是在內(nèi)存中只有基類成員的一份拷貝艺普。舉個例子簸州,一個類叫"動物",另有多各類繼承自動物歧譬,比如"胎生動物"岸浑、"卵生動物",又有多個類繼承自哺乳動物, 比如"人", "貓", "狗"瑰步,這個例子好像復(fù)雜了矢洲,不過很明顯,被實例化的一定是一個個體缩焦,比如"人", "貓", "狗"读虏。而"胎生動物"责静,不應(yīng)該被實例化為一個個體,它僅僅是人類在知識領(lǐng)域掘譬,為了分類世間萬物而抽象的一個分類泰演。但是面向?qū)ο笤O(shè)計要求我們把共性放在一起以減少代碼,因此就有了抽象類葱轩。所以胎生動物都會運動睦焕,都可以發(fā)出聲音,這些就應(yīng)該是共性放在"胎生動物"類中靴拱,而所以動物都會呼吸垃喊,會新陳代謝,這些共性就放在動物里面袜炕,這樣我們就不需要在"人", "貓", "狗"這樣的具體類中一遍遍的實現(xiàn)這些共有的方法和屬性本谜。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市偎窘,隨后出現(xiàn)的幾起案子乌助,更是在濱河造成了極大的恐慌,老刑警劉巖陌知,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件他托,死亡現(xiàn)場離奇詭異,居然都是意外死亡仆葡,警方通過查閱死者的電腦和手機(jī)赏参,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來沿盅,“玉大人把篓,你說我怎么就攤上這事⊙В” “怎么了韧掩?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長窖铡。 經(jīng)常有香客問我揍很,道長,這世上最難降的妖魔是什么万伤? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮呜袁,結(jié)果婚禮上敌买,老公的妹妹穿的比我還像新娘。我一直安慰自己阶界,他們只是感情好虹钮,可當(dāng)我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布聋庵。 她就那樣靜靜地躺著,像睡著了一般芙粱。 火紅的嫁衣襯著肌膚如雪祭玉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天春畔,我揣著相機(jī)與錄音脱货,去河邊找鬼。 笑死律姨,一個胖子當(dāng)著我的面吹牛振峻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播择份,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼扣孟,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了荣赶?” 一聲冷哼從身側(cè)響起凤价,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拔创,沒想到半個月后利诺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡伏蚊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年立轧,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片躏吊。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡氛改,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出比伏,到底是詐尸還是另有隱情胜卤,我是刑警寧澤,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布赁项,位于F島的核電站葛躏,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏悠菜。R本人自食惡果不足惜舰攒,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望悔醋。 院中可真熱鬧摩窃,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蒂秘,卻和暖如春泽本,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背姻僧。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工规丽, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人段化。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓嘁捷,卻偏偏與公主長得像,于是被迫代替她去往敵國和親显熏。 傳聞我的和親對象是個殘疾皇子雄嚣,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,629評論 2 354

推薦閱讀更多精彩內(nèi)容

  • class的基本用法 概述 JavaScript語言的傳統(tǒng)方法是通過構(gòu)造函數(shù),定義并生成新對象喘蟆。下面是一個例子: ...
    呼呼哥閱讀 4,092評論 3 11
  • ES6 class類知識點梳理 大概從幾個方面來講解ES6 class類和傳統(tǒng)的構(gòu)造函數(shù)的區(qū)別缓升。 必須要有cons...
    sunny519111閱讀 465評論 0 1
  • 1.簡單介紹 JavaScript傳統(tǒng)的方法是通過構(gòu)造函數(shù)定義并生成新對象;且ES5里面的繼承是通過原型鏈來實現(xiàn)的...
    _花閱讀 276評論 0 1
  • 注:此篇文章是我參考阮一峰老師的[ECMAScript 6 入門]文章蕴轨,自己記錄的筆記港谊,詳細(xì)的內(nèi)容請移步阮一峰老師...
    HW_____T閱讀 518評論 0 1
  • 突如其來的慵懶聲音,讓得牧塵面龐上的神情一點點的凝固下來橙弱,片刻后歧寺,他終于是有些回過神來,但依舊還是有些難以置信的喃...
    混沌天書閱讀 195評論 0 0