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

資訊專欄INFORMATION COLUMN

揭秘babel的魔法之class魔法處理

wqj97 / 1873人閱讀

摘要:年,很多人已經(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)行編譯。很多人可能沒有關(guān)心過(guò),經(jīng)過(guò)Babel編譯之后,我們?nèi)A麗的ES6代碼究竟變成了什么樣子?

這篇文章,針對(duì)Babel對(duì)ES6里面“類class”的編譯進(jìn)行分析,你可以在線測(cè)試編譯結(jié)果,畢竟紙上得來(lái)終覺淺,自己動(dòng)手,才能真正體會(huì)其中的奧秘。

另外,如果你還不明白JS中原型鏈等OOP相關(guān)知識(shí),建議出門左轉(zhuǎn)找到經(jīng)典的《JS高級(jí)程序設(shè)計(jì)》來(lái)補(bǔ)課;如果你對(duì)JS中,通過(guò)原型鏈來(lái)實(shí)現(xiàn)繼承一直云里霧里,安利一下我的同事,前端著名網(wǎng)紅顏海鏡大大早在2014年的文章

為什么使用選擇Babel

Babel:The compiler for writing next generation JavaScript;
我們知道,現(xiàn)在大部分瀏覽器或者類似NodeJS的javascript引擎還不能直接支持ES6語(yǔ)法。但這并不構(gòu)成障礙,比如Babel的出現(xiàn),使得我們?cè)谏a(chǎn)環(huán)境中書寫ES6代碼成為了現(xiàn)實(shí),它工作原理是編譯ES6的新特性為老版本的ES5,從而得到宿主環(huán)境的支持。

Class例子

在這篇文章中,我會(huì)講解Babel如何處理ES6新特性:Class,這其實(shí)是一系列語(yǔ)法糖的實(shí)現(xiàn)。

Old school方式實(shí)現(xiàn)繼承

在探究ES6之前,我們先來(lái)回顧一下ES5環(huán)境下,我們?nèi)绾螌?shí)現(xiàn)類的繼承:

// Person是一個(gè)構(gòu)造器
function Person(name) {
    this.type = "Person";
    this.name = name;
}

// 我們可以通過(guò)prototype的方式來(lái)加一條實(shí)例方法
Person.prototype.hello = function() {
    console.log("hello " + this.name);
}

// 對(duì)于私有屬性(Static method),我們當(dāng)然不能放在原型鏈上了。我們可以直接放在構(gòu)造函數(shù)上面
Person.fn = function() {
    console.log("static");
};

我們可以這么應(yīng)用:

var julien = new Person("julien");
var darul = new Person("darul");
julien.hello(); // "hello julien"
darul.hello(); // "hello darul"
Person.fn(); // "static"

// 這樣會(huì)報(bào)錯(cuò),因?yàn)閒n是一個(gè)私有屬性
julien.fn(); //Uncaught TypeError: julien.fn is not a function
New school方式(ES6)實(shí)現(xiàn)繼承

在ES6環(huán)境下,我們當(dāng)然迫不及待地試一試Class:

class Person {
    constructor(name) {
        this.name = name;
        this.type="person"
    }
    hello() {
        console.log("hello " + this.name);
    }
    static fn() {
        console.log("static");
    };
}

這樣寫起來(lái)當(dāng)然很cool,但是經(jīng)過(guò)Babel編譯,我們的代碼是什么樣呢?

Babel transformation

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

Step1: 定義
我們從最簡(jiǎn)單開始,試試不加任何方法和屬性的情況下,

Class Person{}

被編譯為:

function _classCallCheck(instance, Constructor) {
    // 檢查是否成功創(chuàng)建了一個(gè)對(duì)象
    if (!(instance instanceof Constructor)) {  
        throw new TypeError("Cannot call a class as a function"); 
    } 
}

var Person = function Person() {
    _classCallCheck(this, Person);
};

你可能會(huì)一頭霧水,_classCallCheck是什么?其實(shí)很簡(jiǎn)單,它是為了保證調(diào)用的安全性。
比如我們這么調(diào)用:

// ok
var p = new Person();

是沒有問題的,但是直接調(diào)用:

// Uncaught TypeError: Cannot call a class as a function
Person();

就會(huì)報(bào)錯(cuò),這就是_classCallCheck所起的作用。具體原理自己看代碼就好了,很好理解。

我們發(fā)現(xiàn),Class關(guān)鍵字會(huì)被編譯成構(gòu)造函數(shù),于是我們便可以通過(guò)new來(lái)實(shí)現(xiàn)實(shí)例的生成。

Step2:Constructor探秘
我們這次嘗試加入constructor,再來(lái)看看編譯結(jié)果:

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

編譯結(jié)果:

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

看上去棒極了,我們繼續(xù)探索。

Step3:增加方法
我們嘗試給Person類添加一個(gè)方法:hello:

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

    hello() {
        console.log("hello " + this.name);
    }
}

編譯結(jié)果(已做適當(dāng)省略):

// 如上,已經(jīng)解釋過(guò)
function _classCallCheck.... 

// MAIN FUNCTION
var _createClass = (function () { 
    function defineProperties(target, props) { 
        for (var i = 0; i < props.length; i++) { 
            var descriptor = props[i]; 
            descriptor.enumerable = descriptor.enumerable || false; 
            descriptor.configurable = true; 
            if ("value" in descriptor) 
            descriptor.writable = true; 
            Object.defineProperty(target, descriptor.key, descriptor); 
        } 
    } 
    return function (Constructor, protoProps, staticProps) { 
        if (protoProps) 
            defineProperties(Constructor.prototype, protoProps); 
        if (staticProps) 
            defineProperties(Constructor, staticProps); 
        return Constructor; 
    }; 
})();

var Person = (function () {
    function Person(name) {
        _classCallCheck(this, Person);

        this.name = name;
    }

    _createClass(Person, [{
        key: "hello",
        value: function hello() {
            console.log("hello " + this.name);
        }
    }]);

    return Person;
})();

Oh...no,看上去有很多需要消化!不要急,我嘗試先把他精簡(jiǎn)一下,并加上注釋,你就會(huì)明白核心思路:

var _createClass = (function () {   
    function defineProperties(target, props) { 
        // 對(duì)于每一個(gè)定義的屬性props,都要完全拷貝它的descriptor,并擴(kuò)展到target上
    }  
    return defineProperties(Constructor.prototype, protoProps);    
})();

var Person = (function () {
    function Person(name) { // 同之前... }

    _createClass(Person, [{
        key: "hello",
        value: function hello() {
            console.log("hello " + this.name);
        }
    }]);

    return Person;
})();

如果你不明白defineProperty方法, 請(qǐng)參考這里

現(xiàn)在,我們知道我們添加的方法:

hello() {
    console.log("hello " + this.name);
}

被編譯為:

_createClass(
    Person, [{
    key: "hello",
    value: function hello() {
        console.log("hello " + this.name);
    }
}]);

而_createClass接受2個(gè)-3個(gè)參數(shù),分別表示:

參數(shù)1 => 我們要擴(kuò)展屬性的目標(biāo)對(duì)象,這里其實(shí)就是我們的Person
參數(shù)2 => 需要在目標(biāo)對(duì)象原型鏈上添加的屬性,這是一個(gè)數(shù)組
參數(shù)3 => 需要在目標(biāo)對(duì)象上添加的屬性,這是一個(gè)數(shù)組

這樣,Babel的魔法就一步一步被揭穿了。

總結(jié)

希望這篇文章能夠讓你了解到Babel是如何初步把我們ES6 Class語(yǔ)法編譯成ES5的。下一篇文章我會(huì)繼續(xù)介紹Babel如何處理子類的Super(), 并會(huì)通過(guò)一段函數(shù)橋梁,使得ES5環(huán)境下也能夠繼承ES6定義的Class。

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

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

相關(guān)文章

  • 揭秘babel魔法class繼承處理2

    摘要:并且用驗(yàn)證了中一系列的實(shí)質(zhì)就是魔法糖的本質(zhì)。抽絲剝繭我們首先看的編譯結(jié)果這是一個(gè)自執(zhí)行函數(shù),它接受一個(gè)參數(shù)就是他要繼承的父類,返回一個(gè)構(gòu)造函數(shù)。 如果你已經(jīng)看過(guò)第一篇揭秘babel的魔法之class魔法處理,這篇將會(huì)是一個(gè)延伸;如果你還沒看過(guò),并且也不想現(xiàn)在就去讀一下,單獨(dú)看這篇也沒有關(guān)系,并不存在理解上的障礙。 上一篇針對(duì)Babel對(duì)ES6里面基礎(chǔ)class的編譯進(jìn)行了分析。這一篇將...

    BlackHole1 評(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
  • 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:...

    fantix 評(píng)論0 收藏0
  • (譯)React hooks:它不是一種魔法,只是一個(gè)數(shù)組——使用圖表揭秘提案規(guī)則

    摘要:它并不是實(shí)際在內(nèi)部的工作方式,而且它只是一個(gè)提案,在未來(lái)都會(huì)有可能發(fā)生變化。這意味著,數(shù)據(jù)的存儲(chǔ)是獨(dú)立于組件之外的。因此,有一個(gè)訣竅就是你需要思考作為一組需要一個(gè)匹配一致的指針去管理的數(shù)組染陌譯。 原文地址:https://medium.com/@ryardley/... 譯文:染陌 (Github) 譯文地址:https://github.com/answershuto/Blog 轉(zhuǎn)...

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

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

0條評(píng)論

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