成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

【ES6】更易于繼承的類(lèi)語(yǔ)法

Lionad-Morotar / 566人閱讀

摘要:的類(lèi)使用熟悉的關(guān)鍵字指定類(lèi)繼承的函數(shù),并且可以通過(guò)方法訪問(wèn)父類(lèi)的構(gòu)造函數(shù)。例如繼承一個(gè)的類(lèi)繼承了,術(shù)語(yǔ)上稱(chēng)為基類(lèi),為派生類(lèi)。例如注意到上例中,不僅是派生類(lèi)的實(shí)例,也是派生類(lèi)的實(shí)例,內(nèi)建對(duì)象繼承的實(shí)用之處是改變返回對(duì)象的類(lèi)型。

和其它面向?qū)ο缶幊陶Z(yǔ)言一樣,ES6 正式定義了 class 類(lèi)以及 extend 繼承語(yǔ)法糖,并且支持靜態(tài)、派生、抽象、迭代、單例等,而且根據(jù) ES6 的新特性衍生出很多有趣的用法。
一、類(lèi)的基本定義

基本所有面向?qū)ο蟮恼Z(yǔ)言都支持類(lèi)的封裝與繼承,那什么是類(lèi)?

類(lèi)是面向?qū)ο蟪绦蛟O(shè)計(jì)的基礎(chǔ),包含數(shù)據(jù)封裝、數(shù)據(jù)操作以及傳遞消息的函數(shù)。類(lèi)的實(shí)例稱(chēng)為對(duì)象。

ES5 之前通過(guò)函數(shù)來(lái)模擬類(lèi)的實(shí)現(xiàn)如下:

// 構(gòu)造函數(shù)
function Person(name) {
  this.name = name;
}
// 原型上的方法
Person.prototype.sayName = function(){
  console.log(this.name);
};
// new 一個(gè)實(shí)例
var friend = new Person("Jenny");

friend.sayName(); // Jenny
console.log(friend instanceof Person);   // true
console.log(friend instanceof Object);   // true

總結(jié)來(lái)說(shuō),定義一個(gè)類(lèi)的思路如下

1.需要構(gòu)造函數(shù)封裝數(shù)據(jù)

2.在原型上添加方法操作數(shù)據(jù),

3.通過(guò)New創(chuàng)建實(shí)例

ES6 使用class關(guān)鍵字定義一個(gè)類(lèi),這個(gè)類(lèi)有特殊的方法名[[Construct]]定義構(gòu)造函數(shù),在 new 創(chuàng)建實(shí)例時(shí)調(diào)用的就是[[Construct]],示例如下:

/*ES6*/
// 等價(jià)于 let Person = class {
class Person {
  // 構(gòu)造函數(shù)
  constructor(name) {
    this.name = name;
  }
  // 等價(jià)于Person.prototype.sayName
  sayName() {
    console.log(this.name);
  }
}

console.log(typeof Person);   // function
console.log(typeof Person.prototype.sayName);   // function

let friend = new Person("Jenny");

friend.sayName(); // Jenny
console.log(friend instanceof Person);   // true
console.log(friend instanceof Object);   // true

上面的例子中class定義的類(lèi)與自定義的函數(shù)模擬類(lèi)功能上貌似沒(méi)什么不同,但本質(zhì)上還有很大差異的:

函數(shù)聲明可以被提升,但是class類(lèi)聲明與let類(lèi)似,不能被提升;

類(lèi)聲明自動(dòng)運(yùn)行在嚴(yán)格模式下,“use strict”;

類(lèi)中所有方法都是不可枚舉的,enumerable 為 false。

二、更靈活的類(lèi)

類(lèi)和函數(shù)一樣,是JavaScript的一等公民(可以傳入函數(shù)、從函數(shù)返回、賦值),并且注意到類(lèi)與對(duì)象字面量還有更多相似之處,這些特點(diǎn)可以擴(kuò)展出類(lèi)更靈活的定義與使用。

2.1 擁有訪問(wèn)器屬性

對(duì)象的屬性有數(shù)據(jù)屬性和訪問(wèn)屬性,類(lèi)中也可以通過(guò)getset關(guān)鍵字定義訪問(wèn)器屬性:

class Person {
  constructor(name) {
    this.name = name;
  }

  get value () {
    return this.name + this.age
  }
  set value (num) {
    this.age = num
  }
}

let friend = new Person("Jenny");
// 調(diào)用的是 setter
friend.value = 18
// 調(diào)用的是 getter
console.log(friend.value) // Jenny18
2.2 可計(jì)算的成員名稱(chēng)

類(lèi)似 ES6 對(duì)象字面量擴(kuò)展的可計(jì)算屬性名稱(chēng),類(lèi)也可以用[表達(dá)式]定義可計(jì)算成員名稱(chēng),包括類(lèi)中的方法和訪問(wèn)器屬性:

let methodName = "sayName"

class Person {
  constructor(name) {
    this.name = name;
  }

  [methodName + "Default"]() {
    console.log(this.name);
  }

  get [methodName]() {
    return this.name
  }

  set [methodName](str) {
    this.name = str
  }
}

let friend = new Person("Jenny");

// 方法
friend.sayNameDefault(); // Jenny
// 訪問(wèn)器屬性
friend.sayName = "lee"
console.log(friend.sayName) // lee
想進(jìn)一步熟悉對(duì)象新特性可參考:【ES6】對(duì)象的新功能與解構(gòu)賦值
2.3 定義默認(rèn)迭代器

ES6 中常用的集合對(duì)象(數(shù)組、Set/Map集合)和字符串都是可迭代對(duì)象,如果類(lèi)是用來(lái)表示值這些可迭代對(duì)象的,那么定義一個(gè)默認(rèn)迭代器會(huì)更有用。

ES6 通過(guò)給Symbol.iterator屬性添加生成器的方式,定義默認(rèn)迭代器:

class Person {
  constructor(name) {
    this.name = name;
  }

  *[Symbol.iterator]() {
    for (let item of this.name){
      yield item
    }
  }
}

var abbrName = new Person(new Set(["j", "j", "e", "e", "n", "y", "y", "y",]))
for (let x of abbrName) {
  console.log(x); // j e n y
}
console.log(...abbrName) // j e n y

定義默認(rèn)迭代器后類(lèi)的實(shí)例就可以使用for-of循環(huán)和展開(kāi)運(yùn)算符(...)等迭代功能。

對(duì)以上迭代器內(nèi)容感到困惑的可參考:【ES6】迭代器與可迭代對(duì)象
2.4 作為參數(shù)的類(lèi)

類(lèi)作為"一等公民”可以當(dāng)參數(shù)使用傳入函數(shù)中,當(dāng)然也可以從函數(shù)中返回:

function createClass(className, val) {
  return new className(val)
}

let person = createClass(Person,"Jenny")
console.log(person) // Person { name: "Jenny" }
console.log(typeof person) // object
2.5 創(chuàng)建單例

使用類(lèi)語(yǔ)法創(chuàng)建單例的方式通過(guò)new立即調(diào)用類(lèi)表達(dá)式

let singleton = new class {
  constructor(name) {
    this.name = name;
  }
}("Jenny")
 
console.log(singleton.name) // Jenny

這里先創(chuàng)建匿名類(lèi)表達(dá)式,然后 new 調(diào)用這個(gè)類(lèi)表達(dá)式,并通過(guò)小括號(hào)立即執(zhí)行,這種類(lèi)語(yǔ)法創(chuàng)建的單例不會(huì)在作用域中暴露類(lèi)的引用。

三、類(lèi)的繼承

回顧 ES6 之前如何實(shí)現(xiàn)繼承?常用方式是通過(guò)原型鏈、構(gòu)造函數(shù)以及組合繼承等方式。

ES6 的類(lèi)使用熟悉的extends關(guān)鍵字指定類(lèi)繼承的函數(shù),并且可以通過(guò)surpe()方法訪問(wèn)父類(lèi)的構(gòu)造函數(shù)。

例如繼承一個(gè) Person 的類(lèi):

class Friend extends Person {
  constructor(name, phone){
    super(name)
    this.phone = phone
  }
}

let myfriend = new Friend("lee",2233)
console.log(myfriend) // Friend { name: "lee", phone: 2233 }

Friend 繼承了 Person,術(shù)語(yǔ)上稱(chēng) Person 為基類(lèi),F(xiàn)riend 為派生類(lèi)。

需要注意的是,surpe()只能在派生類(lèi)中使用,它負(fù)責(zé)初始化 this,所以派生類(lèi)使用 this 之前一定要用surpe()。

3.1 繼承內(nèi)建對(duì)象

ES6 的類(lèi)繼承可以繼承內(nèi)建對(duì)象(Array、Set、Map 等),繼承后可以擁有基類(lèi)的所有內(nèi)建功能。例如:

class MyArray extends Array {
}

let arr = new MyArray(1, 2, 3, 4),
  subarr = arr.slice(1, 3)

console.log(arr.length) // 4
console.log(arr instanceof MyArray) // true
console.log(arr instanceof Array) // true
console.log(subarr instanceof MyArray) // true

注意到上例中,不僅 arr 是派生類(lèi) MyArray 的實(shí)例,subarr 也是派生類(lèi) MyArray 的實(shí)例,內(nèi)建對(duì)象繼承的實(shí)用之處是改變返回對(duì)象的類(lèi)型。

瀏覽器引擎背后是通過(guò)[Symbol.species]屬性實(shí)現(xiàn)這一行為,它被用于返回函數(shù)的靜態(tài)訪問(wèn)器屬性,內(nèi)建對(duì)象定義了[Symbol.species]屬性的有 Array、ArrayBuffer、Set、Map、Promise、RegExp、Typed arrays。
3.2 繼承表達(dá)式的類(lèi)

目前extends可以繼承類(lèi)和內(nèi)建對(duì)象,但更強(qiáng)大的功能從表達(dá)式導(dǎo)出類(lèi)!

這個(gè)表達(dá)式要求可以被解析為函數(shù)并具有[[Construct]]屬性和原型,示例如下:

function Sup(val) {
  this.value = val
}

Sup.prototype.getVal = function () {
  return "hello" + this.value
}

class Derived extends Sup {
  constructor(val) {
    super(val)
  }
}

let der = new Derived("world")
console.log(der) // Derived { value: "world" }
console.log(der.getVal()) // helloworld
3.3 只能繼承的抽象類(lèi)

ES6 引入new.target元屬性判斷函數(shù)是否通過(guò)new關(guān)鍵字調(diào)用。類(lèi)的構(gòu)造函數(shù)也可以通過(guò)new.target確定類(lèi)是如何被調(diào)用的。

可以通過(guò)new.target創(chuàng)建抽象類(lèi)(不能實(shí)例化的類(lèi)),例如:

class Abstract  {
  constructor(){
    if(new.target === Abstract) {
      throw new Error("抽象類(lèi)(不能直接實(shí)例化)")
    }
  }
}

class Instantiable extends Abstract {
  constructor() {
    super()
  }
}

// let abs = new Abstract() // Error: 抽象類(lèi)(不能直接實(shí)例化)
 let abs = new Instantiable()
console.log(abs instanceof Abstract) // true

雖然不能直接使用 Abstract 抽象類(lèi)創(chuàng)建實(shí)例,但是可以作為基類(lèi)派生其它類(lèi)。

四、類(lèi)的靜態(tài)成員

ES6 使用static關(guān)鍵字聲明靜態(tài)成員或方法。在類(lèi)的方法或訪問(wèn)器屬性前都可以使用static,唯一的限制是不能用于構(gòu)造函數(shù)。

靜態(tài)成員的作用是某些類(lèi)成員的私有化,及不可在實(shí)例中訪問(wèn),必須要直接在類(lèi)上訪問(wèn)。

class Person {
  constructor(name) {
    this.name = name;
  }

  static create(name) {
    return new Person(name);
  }
}

let beauty = Person.create("Jenny");
// beauty.create("lee") // TypeError

如果基類(lèi)有靜態(tài)成員,那這些靜態(tài)成員在派生類(lèi)也可以使用。

例如將上例的 Person 作為基類(lèi),派生出 Friend 類(lèi)并使用基類(lèi)的靜態(tài)方法create( ):

class Friend extends Person {
  constructor(name){
    super(name)
  }
}

var friend = Friend.create("lee")
console.log(friend instanceof Person) // true
console.log(friend instanceof Friend) // false

可以看出派生類(lèi)依然可以使用基類(lèi)的靜態(tài)方法。

推薦閱讀《深入理解ES6》

加油哦少年!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/98979.html

相關(guān)文章

  • es6 - 類(lèi)

    摘要:創(chuàng)建自定義類(lèi)型看下面一段代碼上面代碼使用創(chuàng)建了一個(gè)自定義類(lèi)型,是這個(gè)類(lèi)的構(gòu)造器,是類(lèi)的公共方法。注意事項(xiàng)在使用類(lèi)繼承的實(shí)現(xiàn)中,需要注意的點(diǎn)是如果子類(lèi)沒(méi)有重寫(xiě)方法,默認(rèn)會(huì)調(diào)用父類(lèi)的構(gòu)造器方法。 es6 類(lèi)-class 與大多正規(guī)的面向?qū)ο缶幊陶Z(yǔ)言不同(比如java),js在創(chuàng)建之初就不支持類(lèi)。js的面向?qū)ο缶幊虒?shí)現(xiàn)方式是通過(guò)構(gòu)造函數(shù)和原型來(lái)實(shí)現(xiàn)的。 我之前以為es6引入類(lèi)的概念將會(huì)帶給這...

    notebin 評(píng)論0 收藏0
  • ES6—class與面向?qū)ο缶幊蹋?)

    摘要:接下來(lái)我們看下類(lèi)的寫(xiě)法,這個(gè)就很接近于傳統(tǒng)面向?qū)ο笳Z(yǔ)言了。如果你想了解傳統(tǒng)面向?qū)ο笳Z(yǔ)言,這里是一個(gè)好切入點(diǎn)。作為對(duì)象時(shí),指向父類(lèi)的原型對(duì)象。這些就是為將來(lái)在中支持面向?qū)ο蟮念?lèi)機(jī)制而預(yù)留的。 在ES5中,我們經(jīng)常使用方法或者對(duì)象去模擬類(lèi)的使用,并基于原型實(shí)現(xiàn)繼承,雖然可以實(shí)現(xiàn)功能,但是代碼并不優(yōu)雅,很多人還是傾向于用 class 來(lái)組織代碼,很多類(lèi)庫(kù)、框架創(chuàng)造了自己的 API 來(lái)實(shí)現(xiàn) c...

    wangjuntytl 評(píng)論0 收藏0
  • JavaScript 中的類(lèi)繼承

    摘要:因?yàn)椴僮鞣麆?chuàng)建的對(duì)象都繼承自構(gòu)造函數(shù)的屬性。繼承的實(shí)現(xiàn)中常用的繼承方式是組合繼承,也就是通過(guò)構(gòu)造函數(shù)和原型鏈繼承同時(shí)來(lái)模擬繼承的實(shí)現(xiàn)。 原文發(fā)布在我的博客 我們都知道 JavaScript 是一門(mén)基于原型的語(yǔ)言。當(dāng)我們調(diào)用一個(gè)對(duì)象本身沒(méi)有的屬性時(shí),JavaScript 就會(huì)從對(duì)象的原型對(duì)象上去找該屬性,如果原型上也沒(méi)有該屬性,那就去找原型的原型,一直找原型鏈的末端也就是 Object....

    rottengeek 評(píng)論0 收藏0
  • es6之js的類(lèi)

    摘要:生成的類(lèi)的原型會(huì)被自動(dòng)調(diào)整,而你還能調(diào)用方法來(lái)訪問(wèn)基類(lèi)的構(gòu)造器。唯一能避免調(diào)用的辦法,是從類(lèi)構(gòu)造器中返回一個(gè)對(duì)象。 起源 JS 從創(chuàng)建之初就不支持類(lèi),也沒(méi)有把類(lèi)繼承作為定義相似對(duì)象以及關(guān)聯(lián)對(duì)象的主要方式,這讓不少開(kāi)發(fā)者感到困惑。而從 ES1 誕生之前直到ES5 時(shí)期,很多庫(kù)都創(chuàng)建了一些工具,讓 JS 顯得貌似能支持類(lèi)。盡管一些 JS 開(kāi)發(fā)者強(qiáng)烈認(rèn)為這門(mén)語(yǔ)言不需要類(lèi),但為處理類(lèi)而創(chuàng)建的代...

    libin19890520 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<