国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

揭秘babel的魔法之class繼承的處理2

BlackHole1 / 567人閱讀

摘要:并且用驗(yàn)證了中一系列的實(shí)質(zhì)就是魔法糖的本質(zhì)。抽絲剝繭我們首先看的編譯結(jié)果這是一個(gè)自執(zhí)行函數(shù),它接受一個(gè)參數(shù)就是他要繼承的父類,返回一個(gè)構(gòu)造函數(shù)。

如果你已經(jīng)看過(guò)第一篇揭秘babel的魔法之class魔法處理,這篇將會(huì)是一個(gè)延伸;
如果你還沒(méi)看過(guò),并且也不想現(xiàn)在就去讀一下,多帶帶看這篇也沒(méi)有關(guān)系,并不存在理解上的障礙。

上一篇針對(duì)Babel對(duì)ES6里面基礎(chǔ)“class”的編譯進(jìn)行了分析。這一篇將會(huì)對(duì)class的繼承,包括extends和super進(jìn)行講解。

什么?你還不了解ES6如何實(shí)現(xiàn)繼承?沒(méi)關(guān)系,下文內(nèi)容也有詳細(xì)示例。

再啰嗦一句,這一系列的文章并不是科普ECMAScript新規(guī)范。她的意義在于分析Babel對(duì)ES6的編譯,從而希望讀者對(duì)JS語(yǔ)言基礎(chǔ),程序設(shè)計(jì)理念等有更深刻的認(rèn)識(shí)。

Class的繼承

在這篇文章中,我會(huì)講解Babel如何處理ES6 Class里面的繼承功能,同樣,這其實(shí)是一系列語(yǔ)法糖的實(shí)現(xiàn)。
我們先來(lái)溫習(xí)一下實(shí)現(xiàn)方式:

ES6 實(shí)現(xiàn)繼承

首先,我們定義一個(gè)父類:

class Person {
    constructor(){
        this.type = "person"
    }
}

這個(gè)類包含了一個(gè)實(shí)例屬性。

然后,實(shí)現(xiàn)一個(gè)Student類,這個(gè)“學(xué)生”類繼承“人”類:

class Student extends Person {
    constructor(){
        super()
    }
}

從簡(jiǎn)出發(fā),我們定義的Person類只包含了type為person的這一個(gè)屬性,不含有方法。所以我們extends+super()之后,Student類
也繼承了同樣的屬性。
如下:

var student1 = new Student();
student1.type // "person"

我們進(jìn)一步可以驗(yàn)證原型鏈上的關(guān)系:

student1 instanceof Student // true
student1 instanceof Person // true
student1.hasOwnProperty("type") // true

一切看上去cool極了,我們實(shí)現(xiàn)了ES6里面的繼承。并且用instanceof驗(yàn)證了ES6中一系列的實(shí)質(zhì)就是“魔法糖”的本質(zhì)。
那么,經(jīng)過(guò)Babel編譯,我們的代碼是什么樣呢?

Babel transformation

我們一步一步來(lái)看,

Step1: Person定義

class Person {
    constructor(){
        this.type = "person"
    }
}

被編譯為:

var Person = function Person() {
    _classCallCheck(this, Person);
    this.type = "person";
};

如果你看過(guò)這一篇的前傳,
你應(yīng)該就熟悉這一系列的變換,也可能會(huì)記得_classCallCheck函數(shù)到底是什么鬼。這里因?yàn)槠腿ト哂嗟脑颍筒辉僬归_。

Step2:Student探秘
我們這次嘗試觀察Student子類:

class Student extends Person {
    constructor(){
        super()
    }
}

編譯結(jié)果:

// 實(shí)現(xiàn)定義Student構(gòu)造函數(shù),它是一個(gè)自執(zhí)行函數(shù),接受父類構(gòu)造函數(shù)為參數(shù)
var Student = (function(_Person) {
    // 實(shí)現(xiàn)對(duì)父類原型鏈屬性的繼承
    _inherits(Student, _Person);
    
    // 將會(huì)返回這個(gè)函數(shù)作為完整的Student構(gòu)造函數(shù)
    function Student() {
        // 使用檢測(cè)
        _classCallCheck(this, Student);  
        // _get的返回值可以先理解為父類構(gòu)造函數(shù)       
        _get(Object.getPrototypeOf(Student.prototype), "constructor", this).call(this);
    }

    return Student;
})(Person);

// _x為Student.prototype.__proto__
// _x2為"constructor"
// _x3為this
var _get = function get(_x, _x2, _x3) {
    var _again = true;
    _function: while (_again) {
        var object = _x,
            property = _x2,
            receiver = _x3;
        _again = false;
        // Student.prototype.__proto__為null的處理
        if (object === null) object = Function.prototype;
        // 以下是為了完整復(fù)制父類原型鏈上的屬性,包括屬性特性的描述符
        var desc = Object.getOwnPropertyDescriptor(object, property);
        if (desc === undefined) {
            var parent = Object.getPrototypeOf(object);
            if (parent === null) {
                return undefined;
            } else {
                _x = parent;
                _x2 = property;
                _x3 = receiver;
                _again = true;
                desc = parent = undefined;
                continue _function;
            }
        } else if ("value" in desc) {
            return desc.value;
        } else {
            var getter = desc.get;
            if (getter === undefined) {
                return undefined;
            }
            return getter.call(receiver);
        }
    }
};

function _inherits(subClass, superClass) {
    // superClass需要為函數(shù)類型,否則會(huì)報(bào)錯(cuò)
    if (typeof superClass !== "function" && superClass !== null) {
        throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
    }
    // Object.create第二個(gè)參數(shù)是為了修復(fù)子類的constructor
    subClass.prototype = Object.create(superClass && superClass.prototype, {
        constructor: {
            value: subClass,
            enumerable: false,
            writable: true,
            configurable: true
        }
    });
    // Object.setPrototypeOf是否存在做了一個(gè)判斷,否則使用__proto__
    if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}

雖然我加上了注釋,但是這一坨代碼仍然看上去惡心極了!沒(méi)關(guān)系,下面我們進(jìn)行拆解,你很快就能明白。

Step3:抽絲剝繭
我們首先看Student的編譯結(jié)果:

var Student = (function(_Person) {
    _inherits(Student, _Person);

    function Student() {
        _classCallCheck(this, Student);            
        _get(Object.getPrototypeOf(Student.prototype), "constructor", this).call(this);
    }

    return Student;
})(Person);

這是一個(gè)自執(zhí)行函數(shù),它接受一個(gè)參數(shù)Person(就是他要繼承的父類),返回一個(gè)構(gòu)造函數(shù)Student。

上面_inherits方法的本質(zhì)其實(shí)就是讓Student子類繼承Person父類原型鏈上的方法。它實(shí)現(xiàn)原理可以歸結(jié)為一句話:

Student.prototype = Object.create(Person.prototype);
Object.setPrototypeOf(Student, Person)

注意,Object.create接收第二個(gè)參數(shù),這就實(shí)現(xiàn)了對(duì)Student的constructor修復(fù)。
如果你不了解Object.create,那么請(qǐng)參考這里。

以上通過(guò)_inherits實(shí)現(xiàn)了對(duì)父類原型鏈上屬性的繼承,那么對(duì)于父類的實(shí)例屬性(就是constructor定義的屬性)的繼承,也可以歸結(jié)為一句話:

Person.call(this);

如果你還不理解使用call或者apply或者bind來(lái)改變JS中this的指向,那么請(qǐng)參考這篇文章。

這樣,我們便透析了Babel編譯這一切的秘密。

總結(jié)

如果你看完這一系列的文章可能會(huì)有體會(huì):我想灌輸?shù)目隙ú皇荅S6新特性的使用,關(guān)于這些東西有太多的文章、博客、書籍去討論。

我是在講Babel對(duì)這些新特性的編譯產(chǎn)出,那為什么我會(huì)在乎這些呢?
其實(shí)通過(guò)分析,我們悄然回顧了JS中很多重點(diǎn)以及難點(diǎn),還包括程序設(shè)計(jì)上的一些小思想。
最近面試了很多前端“新同學(xué)”:有的人癡迷于框架,可以使用React或者Vue比照tutorial做出頁(yè)面炫酷的交互,甚至自覺(jué)SPA也不在話下;
有的人ES6、ES7了解很多,generator,async都能說(shuō)出一二,仿佛Promise處理異步已經(jīng)成為了“時(shí)代棄兒”。
可是同樣是這些人,對(duì)原型原型鏈、this、作用域、閉包都沒(méi)有深刻地理解和掌握。
同樣是這些頁(yè)面,即便用callback處理異步回調(diào),嵌套最多也不到兩層。

也許,同樣一批人也會(huì)問(wèn):“我能用前端框架、ES6擼出好多頁(yè)面,可是為什么感覺(jué)進(jìn)步很慢處于瓶頸中、面試也總被掛呢?”

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/81245.html

相關(guān)文章

  • 揭秘babel魔法class魔法處理

    摘要:年,很多人已經(jīng)開始接觸環(huán)境,并且早已經(jīng)用在了生產(chǎn)當(dāng)中。我們發(fā)現(xiàn),關(guān)鍵字會(huì)被編譯成構(gòu)造函數(shù),于是我們便可以通過(guò)來(lái)實(shí)現(xiàn)實(shí)例的生成。下一篇文章我會(huì)繼續(xù)介紹如何處理子類的并會(huì)通過(guò)一段函數(shù)橋梁,使得環(huán)境下也能夠繼承定義的。 2017年,很多人已經(jīng)開始接觸ES6環(huán)境,并且早已經(jīng)用在了生產(chǎn)當(dāng)中。我們知道ES6在大部分瀏覽器還是跑不通的,因此我們使用了偉大的Babel來(lái)進(jìn)行編譯。很多人可能沒(méi)有關(guān)心過(guò),...

    wqj97 評(píng)論0 收藏0
  • 如何繼承Date對(duì)象?由一道題徹底弄懂JS繼承

    摘要:前言見(jiàn)解有限,如有描述不當(dāng)之處,請(qǐng)幫忙及時(shí)指出,如有錯(cuò)誤,會(huì)及時(shí)修正。倘若用的是中文搜索。所以最終的實(shí)例對(duì)象仍然能進(jìn)行正常的原型鏈回溯,回溯到原本的所有原型方法這樣通過(guò)一個(gè)巧妙的欺騙技巧,就實(shí)現(xiàn)了完美的繼承。 前言 見(jiàn)解有限,如有描述不當(dāng)之處,請(qǐng)幫忙及時(shí)指出,如有錯(cuò)誤,會(huì)及時(shí)修正。 20180201更新: 修改用詞描述,如組合寄生式改成寄生組合式,修改多處筆誤(感謝@Yao Ding的...

    sunnyxd 評(píng)論0 收藏0
  • ES6 探秘:Classes

    摘要:中的同名的實(shí)際上就是我們?cè)诘脑屠^承中使用的構(gòu)造函數(shù),所以中的是對(duì)中的構(gòu)造函數(shù)的一種包裝。我們發(fā)現(xiàn),在中設(shè)定的屬性被放在的構(gòu)造函數(shù)中,而方法則以鍵值對(duì)的形式傳入一個(gè)函數(shù)中。大家是不是對(duì)這種繼承模式似曾相識(shí)呢對(duì)了,這就是所謂的構(gòu)造函數(shù)竊取。 ES6中增加了一些新特性,但從底層的角度來(lái)說(shuō),只是一些語(yǔ)法糖。但是就我個(gè)人來(lái)說(shuō),如果不了解這些語(yǔ)法糖的本質(zhì),是用不安心的。那我們要如何揭開這些語(yǔ)法糖...

    caoym 評(píng)論0 收藏0
  • CSS 魔法:學(xué)海無(wú)涯,而吾生有涯

    摘要:我們都知道您是國(guó)內(nèi)知名的專家,是什么樣的情結(jié)使得您愿意將魔法作為自己的別名大家好,很榮幸接受圖靈的專訪。在這一堆書里,有一套上下冊(cè)教程叫作談是由圖靈引進(jìn)的哦。從偶像那里得來(lái)一個(gè)名字,很榮幸而且這其中也有圖靈的功勞,也是緣份。 非商業(yè)轉(zhuǎn)載請(qǐng)注明作譯者、出處,并保留本文的原始鏈接:http://www.ituring.com.cn/article/216538 showImg(https:...

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

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<