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

資訊專欄INFORMATION COLUMN

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

BlackHole1 / 574人閱讀

摘要:并且用驗證了中一系列的實質就是魔法糖的本質。抽絲剝繭我們首先看的編譯結果這是一個自執行函數,它接受一個參數就是他要繼承的父類,返回一個構造函數。

如果你已經看過第一篇揭秘babel的魔法之class魔法處理,這篇將會是一個延伸;
如果你還沒看過,并且也不想現在就去讀一下,多帶帶看這篇也沒有關系,并不存在理解上的障礙。

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

什么?你還不了解ES6如何實現繼承?沒關系,下文內容也有詳細示例。

再啰嗦一句,這一系列的文章并不是科普ECMAScript新規范。她的意義在于分析Babel對ES6的編譯,從而希望讀者對JS語言基礎,程序設計理念等有更深刻的認識。

Class的繼承

在這篇文章中,我會講解Babel如何處理ES6 Class里面的繼承功能,同樣,這其實是一系列語法糖的實現。
我們先來溫習一下實現方式:

ES6 實現繼承

首先,我們定義一個父類:

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

這個類包含了一個實例屬性。

然后,實現一個Student類,這個“學生”類繼承“人”類:

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

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

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

我們進一步可以驗證原型鏈上的關系:

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

一切看上去cool極了,我們實現了ES6里面的繼承。并且用instanceof驗證了ES6中一系列的實質就是“魔法糖”的本質。
那么,經過Babel編譯,我們的代碼是什么樣呢?

Babel transformation

我們一步一步來看,

Step1: Person定義

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

被編譯為:

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

如果你看過這一篇的前傳,
你應該就熟悉這一系列的變換,也可能會記得_classCallCheck函數到底是什么鬼。這里因為篇幅和去冗余的原因,就不再展開。

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

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

編譯結果:

// 實現定義Student構造函數,它是一個自執行函數,接受父類構造函數為參數
var Student = (function(_Person) {
    // 實現對父類原型鏈屬性的繼承
    _inherits(Student, _Person);
    
    // 將會返回這個函數作為完整的Student構造函數
    function Student() {
        // 使用檢測
        _classCallCheck(this, Student);  
        // _get的返回值可以先理解為父類構造函數       
        _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;
        // 以下是為了完整復制父類原型鏈上的屬性,包括屬性特性的描述符
        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需要為函數類型,否則會報錯
    if (typeof superClass !== "function" && superClass !== null) {
        throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
    }
    // Object.create第二個參數是為了修復子類的constructor
    subClass.prototype = Object.create(superClass && superClass.prototype, {
        constructor: {
            value: subClass,
            enumerable: false,
            writable: true,
            configurable: true
        }
    });
    // Object.setPrototypeOf是否存在做了一個判斷,否則使用__proto__
    if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}

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

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

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

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

    return Student;
})(Person);

這是一個自執行函數,它接受一個參數Person(就是他要繼承的父類),返回一個構造函數Student。

上面_inherits方法的本質其實就是讓Student子類繼承Person父類原型鏈上的方法。它實現原理可以歸結為一句話:

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

注意,Object.create接收第二個參數,這就實現了對Student的constructor修復。
如果你不了解Object.create,那么請參考這里。

以上通過_inherits實現了對父類原型鏈上屬性的繼承,那么對于父類的實例屬性(就是constructor定義的屬性)的繼承,也可以歸結為一句話:

Person.call(this);

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

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

總結

如果你看完這一系列的文章可能會有體會:我想灌輸的肯定不是ES6新特性的使用,關于這些東西有太多的文章、博客、書籍去討論。

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

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

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/81245.html

相關文章

  • 揭秘babel魔法class魔法處理

    摘要:年,很多人已經開始接觸環境,并且早已經用在了生產當中。我們發現,關鍵字會被編譯成構造函數,于是我們便可以通過來實現實例的生成。下一篇文章我會繼續介紹如何處理子類的并會通過一段函數橋梁,使得環境下也能夠繼承定義的。 2017年,很多人已經開始接觸ES6環境,并且早已經用在了生產當中。我們知道ES6在大部分瀏覽器還是跑不通的,因此我們使用了偉大的Babel來進行編譯。很多人可能沒有關心過,...

    wqj97 評論0 收藏0
  • 如何繼承Date對象?由一道題徹底弄懂JS繼承

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

    sunnyxd 評論0 收藏0
  • ES6 探秘:Classes

    摘要:中的同名的實際上就是我們在的原型繼承中使用的構造函數,所以中的是對中的構造函數的一種包裝。我們發現,在中設定的屬性被放在的構造函數中,而方法則以鍵值對的形式傳入一個函數中。大家是不是對這種繼承模式似曾相識呢對了,這就是所謂的構造函數竊取。 ES6中增加了一些新特性,但從底層的角度來說,只是一些語法糖。但是就我個人來說,如果不了解這些語法糖的本質,是用不安心的。那我們要如何揭開這些語法糖...

    caoym 評論0 收藏0
  • CSS 魔法:學海無涯,而吾生有涯

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

    svtter 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<