最新文章專(zhuān)題視頻專(zhuān)題問(wèn)答1問(wèn)答10問(wèn)答100問(wèn)答1000問(wèn)答2000關(guān)鍵字專(zhuān)題1關(guān)鍵字專(zhuān)題50關(guān)鍵字專(zhuān)題500關(guān)鍵字專(zhuān)題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專(zhuān)題關(guān)鍵字專(zhuān)題tag2tag3文章專(zhuān)題文章專(zhuān)題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專(zhuān)題3
問(wèn)答文章1 問(wèn)答文章501 問(wèn)答文章1001 問(wèn)答文章1501 問(wèn)答文章2001 問(wèn)答文章2501 問(wèn)答文章3001 問(wèn)答文章3501 問(wèn)答文章4001 問(wèn)答文章4501 問(wèn)答文章5001 問(wèn)答文章5501 問(wèn)答文章6001 問(wèn)答文章6501 問(wèn)答文章7001 問(wèn)答文章7501 問(wèn)答文章8001 問(wèn)答文章8501 問(wèn)答文章9001 問(wèn)答文章9501
當(dāng)前位置: 首頁(yè) - 科技 - 知識(shí)百科 - 正文

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

來(lái)源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-27 22:01:12
文檔

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

ES6 更易于繼承的類(lèi)語(yǔ)法的使用:和其它面向?qū)ο缶幊陶Z(yǔ)言一樣,ES6 正式定義了 class 類(lèi)以及 extend 繼承語(yǔ)法糖,并且支持靜態(tài)、派生、抽象、迭代、單例等,而且根據(jù) ES6 的新特性衍生出很多有趣的用法。 一、類(lèi)的基本定義 基本所有面向?qū)ο蟮恼Z(yǔ)言都支持類(lèi)的封裝與繼承,那什么是類(lèi)? 類(lèi)是
推薦度:
導(dǎo)讀ES6 更易于繼承的類(lèi)語(yǔ)法的使用:和其它面向?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ū)ο缶幊陶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 擁有訪(fǎng)問(wèn)器屬性

    對(duì)象的屬性有數(shù)據(jù)屬性和訪(fǎng)問(wèn)屬性,類(lèi)中也可以通過(guò)get、set關(guān)鍵字定義訪(fǎng)問(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)中的方法和訪(fǎng)問(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
    // 訪(fǎng)問(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()方法訪(fǎng)問(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)訪(fǎng)問(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)的方法或訪(fǎng)問(wèn)器屬性前都可以使用static,唯一的限制是不能用于構(gòu)造函數(shù)。

    靜態(tài)成員的作用是某些類(lèi)成員的私有化,及不可在實(shí)例中訪(fǎng)問(wèn),必須要直接在類(lèi)上訪(fǎng)問(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)方法。

    聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文檔

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

    ES6 更易于繼承的類(lèi)語(yǔ)法的使用:和其它面向?qū)ο缶幊陶Z(yǔ)言一樣,ES6 正式定義了 class 類(lèi)以及 extend 繼承語(yǔ)法糖,并且支持靜態(tài)、派生、抽象、迭代、單例等,而且根據(jù) ES6 的新特性衍生出很多有趣的用法。 一、類(lèi)的基本定義 基本所有面向?qū)ο蟮恼Z(yǔ)言都支持類(lèi)的封裝與繼承,那什么是類(lèi)? 類(lèi)是
    推薦度:
    標(biāo)簽: 容易 es 繼承
    • 熱門(mén)焦點(diǎn)

    最新推薦

    猜你喜歡

    熱門(mén)推薦

    專(zhuān)題
    Top