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

資訊專欄INFORMATION COLUMN

在使用es6語法class的時(shí)候,babel到底做了什么?

時(shí)飛 / 1975人閱讀

摘要:正常情況,的返回值就是一個(gè)對象,其實(shí)也就是對象。好了,上面算是基本說清楚了使用語法定義類繼承類,到底發(fā)生了什么,如果錯(cuò)誤,還請指正,謝謝

自從有了webpack之后,我們這些jscoder似乎得到了前所未有的解放,箭頭函數(shù),對象解構(gòu),let,const關(guān)鍵字,以及class、extends等等關(guān)鍵字使用得不亦樂乎,反正,webpack會幫我們把這些es6代碼轉(zhuǎn)換成瀏覽器能夠識別的es5代碼,那么,我們有多少人真正的看過,babel轉(zhuǎn)換之后的代碼呢?今天,我就來看一下,當(dāng)我們使用關(guān)鍵詞class的時(shí)候,babel到底做了什么?

1、打開網(wǎng)址:https://babeljs.io/repl

我推薦打開網(wǎng)址:https://babeljs.io/repl,這里我們左邊寫es6代碼,馬上右邊就能轉(zhuǎn)譯出es5代碼,然后,我在左邊輸入了如下代碼:

class A {
  constructor(name) {
      this.name = name
  }
  
  getName() {
      return this.name
  }
}

這是一個(gè)最簡單的類,一個(gè)屬性,一個(gè)方法。

這時(shí)候,右邊框已經(jīng)給我轉(zhuǎn)譯出了瀏覽器可識別的es5代碼了,格式化之后是這樣的:

"use strict";

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;
    };
}();

function _classCallCheck(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
        throw new TypeError("Cannot call a class as a function");
    }
}

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

        this.name = name;
    }

    _createClass(A, [{
        key: "getName",
        value: function getName() {
            return this.name;
        }
    }]);

    return A;
}();

好,現(xiàn)在來分析一下這段代碼。

2、es6里面的類,本質(zhì)上其實(shí)就是一個(gè)函數(shù)
// 自執(zhí)行函數(shù)
var A = function () {
    function A(name) {
        // 這個(gè)函數(shù)的目的其實(shí)是防止這個(gè)構(gòu)造函數(shù)被當(dāng)做普通函數(shù)執(zhí)行
        _classCallCheck(this, A);
        
        this.name = name;
    }

    // 對函數(shù)A執(zhí)行_createClass方法,其實(shí)就是給A的原型上綁定方法
    _createClass(A, [{
        key: "getName", //方法名
        value: function getName() { //函數(shù)體
            return this.name;
        }
    }]);

    return A;
}();

這段代碼,變量A是一個(gè)自執(zhí)行函數(shù)的返回值,該自執(zhí)行函數(shù)的返回值其實(shí)就是我們熟悉的構(gòu)造函數(shù),所以,es6里面的類其實(shí)就是一個(gè)構(gòu)造函數(shù)。

3、_classCallCheck函數(shù)
function _classCallCheck(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
        throw new TypeError("Cannot call a class as a function");
    }
}

這個(gè)函數(shù)特別簡單,當(dāng)執(zhí)行函數(shù)A的時(shí)候,不允許this不是A的子類實(shí)例,比如直接這樣調(diào)用A(),但是在A的子類B中可以這樣調(diào)用:A.apply(this, arguments)。
該函數(shù)的目的是防止構(gòu)造函數(shù)被當(dāng)做普通函數(shù)執(zhí)行。

4、_createClass函數(shù)
//該函數(shù)也是一個(gè)自執(zhí)行的函數(shù),其返回值是一個(gè)函數(shù)
var _createClass = function () {
    // 把props數(shù)組上每一個(gè)對象,通過Object.defineProperty方法,都定義到目標(biāo)對象target上去
    function defineProperties(target, props) {
        for (var i = 0; i < props.length; i++) {
            //這里要確保props[i]是一個(gè)對象,并且有key和value兩個(gè)鍵
            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) {
        // 如果傳入了原型屬性數(shù)組,就把屬性全部定義到Constructor的原型上去
        if (protoProps) defineProperties(Constructor.prototype, protoProps);
        // 如果傳入了靜態(tài)屬性數(shù)組,就把屬性全部定義到Constructor對象自身上去
        if (staticProps) defineProperties(Constructor, staticProps);
        return Constructor;
    };
}();

其實(shí)_createClass函數(shù)做的事情,就是把幾個(gè)方法拷貝到構(gòu)造函數(shù)A的原型上去。

4、使用關(guān)鍵詞extends,發(fā)生了什么?

我在https://babeljs.io/repl 左側(cè)輸入框上加了下面這行代碼:

 class B extends A {}

這時(shí)候,右側(cè)多出了以下幾行代碼:

function _possibleConstructorReturn(self, call) {
    if (!self) {
        throw new ReferenceError("this hasn"t been initialised - super() hasn"t been called");
    }
    return call && (typeof call === "object" || typeof call === "function") ? call : self;
}

function _inherits(subClass, superClass) {
    if (typeof superClass !== "function" && superClass !== null) {
        throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
    }
    subClass.prototype = Object.create(superClass && superClass.prototype, {
        constructor: {
            value: subClass,
            enumerable: false,
            writable: true,
            configurable: true
        }
    });
    if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}

var B = function (_A) {
    _inherits(B, _A);

    function B() {
        _classCallCheck(this, B);
        //這里的重點(diǎn)是第二個(gè)參數(shù):(B.__proto__ || Object.getPrototypeOf(B)).apply(this, arguments);
        //這里其實(shí)是將子類的實(shí)例對象,調(diào)用了父類的構(gòu)造函數(shù)方法,這樣父類的屬性就都可以拷貝到子類上來
        return _possibleConstructorReturn(this, (B.__proto__ || Object.getPrototypeOf(B)).apply(this, arguments));
    }

    return B;
}(A);
5、_inherits函數(shù)
function _inherits(subClass, superClass) {
    //簡單校驗(yàn)
    if (typeof superClass !== "function" && superClass !== null) {
        throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
    }
    //把子類的原型指向父類的原型創(chuàng)建出來的對象(注意不是直接指向父類原型),并且修正constructor屬性為子類自己
    subClass.prototype = Object.create(superClass && superClass.prototype, {
        constructor: {
            value: subClass,
            enumerable: false,
            writable: true,
            configurable: true
        }
    });
    // 這一步操作,其實(shí)是想把superClass放到subClass下,相當(dāng)于subClass.super = superClass,這樣后面的代碼中,subClass里面能方便的引用到superClass函數(shù)
    if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}
6、_possibleConstructorReturn函數(shù)
function _possibleConstructorReturn(self, call) {
    if (!self) {
        throw new ReferenceError("this hasn"t been initialised - super() hasn"t been called");
    }
    return call && (typeof call === "object" || typeof call === "function") ? call : self;
}

如果call不是對象或者函數(shù),即該調(diào)用:(B.__proto__ || Object.getPrototypeOf(B)).apply(this, arguments)的返回值既不是對象,也不是函數(shù),那么,就直接返回當(dāng)前的self,而self其實(shí)就是子類B里面的實(shí)例指針this。正常情況,(B.__proto__ || Object.getPrototypeOf(B)).apply(this, arguments)的返回值就是一個(gè)對象,其實(shí)也就是對象。

好了,上面算是基本說清楚了使用es6語法定義類、繼承類,到底發(fā)生了什么,如果錯(cuò)誤,還請指正,謝謝!

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

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

相關(guān)文章

  • Tree-Shaking并沒什么卵用

    摘要:升級之后,項(xiàng)目的壓縮包并沒有什么明顯變化。這里可以參考下阮老師介紹的基本語法的循環(huán)是通過遍歷器迭代的,循環(huán)數(shù)組時(shí)并非是,然后通過下標(biāo)尋值。樓主好奇為什么不能消除未引用的類。樓主我的代碼沒什么副作用啊。 本文將探討tree-shaking在當(dāng)下(webpack@3, babel@6 以下)的現(xiàn)狀,以及研究為什么tree-shaking依舊舉步維艱的原因,最終總結(jié)當(dāng)下能提高tree-sha...

    cncoder 評論0 收藏0
  • babel 到底將代碼轉(zhuǎn)換成什么鳥樣?

    摘要:大概就是將對象里面的一些屬性轉(zhuǎn)換成數(shù)組,方便解構(gòu)賦值的進(jìn)行。而則更貼近的寫法,性能更好一些,兼容性更好一些,但將這部份代碼再轉(zhuǎn)換成的話會比較麻煩一些感覺這一點(diǎn)并不是缺點(diǎn),有源碼就可以了。上面解決的辦法,實(shí)質(zhì)就是將改成。 原文鏈接:https://github.com/lcxfs1991/blog/issues/9 前言 將babel捧作前端一個(gè)劃時(shí)代的工具一定也不為過,它的出現(xiàn)讓許多程...

    qc1iu 評論0 收藏0
  • 【翻譯】深入理解ES6模塊

    摘要:你可能認(rèn)為和它的新模塊系統(tǒng)出現(xiàn)得有點(diǎn)晚。聚合模塊有時(shí)候一個(gè)包的主模塊只不過是導(dǎo)入包其他所有的模塊,并用統(tǒng)一的方式導(dǎo)出。靜態(tài)動態(tài),或者說規(guī)則如何打破規(guī)則作為一個(gè)動態(tài)編譯語言,令人驚奇的是擁有一個(gè)靜態(tài)的模塊系統(tǒng)。 回想2007年,那時(shí)候我剛加入Mozillas JavaScript團(tuán)隊(duì),那時(shí)候的一個(gè)典型的JavaScript程序只需要一行代碼,聽起來像個(gè)笑話。 兩年后,Google Map...

    icattlecoder 評論0 收藏0
  • 我他喵到底要怎樣才能生產(chǎn)環(huán)境中用上 ES6 模塊化?

    摘要:因此,你還是需要各種各樣雜七雜八的工具來轉(zhuǎn)換你的代碼噢,我可去你媽的吧,這些東西都是干嘛的我就是想用個(gè)模塊化,我到底該用啥子本文正旨在列出幾種可用的在生產(chǎn)環(huán)境中放心使用模塊化的方法,希望能幫到諸位后來者這方面的中文資源實(shí)在是忒少了。 原文發(fā)表在我的博客上。最近搗鼓了一下 ES6 的模塊化,分享一些經(jīng)驗(yàn) :) Python3 已經(jīng)發(fā)布了九年了,Python 社區(qū)卻還在用 Python 2...

    KaltZK 評論0 收藏0
  • 揭秘babel魔法之class繼承處理2

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

    BlackHole1 評論0 收藏0

發(fā)表評論

0條評論

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