欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解babel是如何將class語法糖轉(zhuǎn)換為es5的語法

 更新時(shí)間:2024年02月18日 09:07:52   作者:xxyCoder  
這篇文章主要詳細(xì)介紹了babel是如何將class語法糖轉(zhuǎn)換為es5的語法,文中通過代碼示例給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下

準(zhǔn)備工作

  • 在目錄下創(chuàng)建兩個(gè)文件,分別是index.js和.babelrc
class Parent {
    static type = 'Parent';
    #salary = 0;
    name = '';
    static showType() {
        console.log(this.type)
    }
    #seeSalary() {
        console.log(this.#salary)
    }
    speakName() {
        this.#seeSalary()
        console.log(this.name)
    }
}

class Child extends Parent {
    constructor(name) {
        super();
        this.name = name;
    }
    speakName() {
        super.speakName();
    }
}
{
    "presets": [
        "@babel/preset-env"
    ]
}
npm install @babel/core @babel/cli @babel/preset-env --save-dev
npx babel index.js -o dist.js

編譯后私有變量和方法怎么存儲(chǔ)?

var _salary = new WeakMap();
var _seeSalary = new WeakSet();
var Parent = function () {
  function Parent() {
    _classPrivateMethodInitSpec(this, _seeSalary);
    _classPrivateFieldInitSpec(this, _salary, {
      writable: true,
      value: 0
    });
  }
}
function _seeSalary2() {
  console.log(_classPrivateFieldGet(this, _salary));
}

function _classPrivateMethodInitSpec(obj, privateSet) {
  privateSet.add(obj); 
}
function _classPrivateFieldInitSpec(obj, privateMap, value) {
  privateMap.set(obj, value);
}

  • 總結(jié)這部分代碼:私有變量會(huì)存儲(chǔ)在weakMap中,鍵是對(duì)象,值是變量值;私有方法存儲(chǔ)在weakSet中,鍵是對(duì)象。對(duì)于方法存儲(chǔ)了對(duì)象還不夠,執(zhí)行方法是需要函數(shù)體的,函數(shù)體定義在外部。
  • 問題是,我調(diào)用的是seeSalary又不是seeSalary2。首先要說的是,私有方法只能在類方法中調(diào)用,外部是沒辦法調(diào)用的,那么在方法中調(diào)用的時(shí)候會(huì)對(duì)調(diào)用seeSalary進(jìn)行攔截去執(zhí)行seeSalary2。
  • 還有一個(gè)問題,調(diào)用babel轉(zhuǎn)換為es5的語法,怎么還有weakMapweakSet呢?Babel 是包含編譯和polyfill兩部分的。

編譯后靜態(tài)或公開變量和方法怎么存儲(chǔ)?

var Parent = function() {
  function Parent() {
    ...
    _defineProperty(this, "name", '');
  }
  // 第一個(gè)參數(shù)是public方法,第二個(gè)參數(shù)是static方法
  _createClass(Parent, [{
    key: "speakName",
    value: function speakName() {
      _classPrivateMethodGet(this, _seeSalary, _seeSalary2).call(this);
      console.log(this.name);
    }
  }], [{
    key: "showType",
    value: function showType() {
      console.log(this.type);
    }
  }]);
  return Parent;
}
_defineProperty(Parent, "type", 'Parent');

function _createClass(Constructor, protoProps, staticProps) { 
  if (protoProps) _defineProperties(Constructor.prototype, protoProps); 
  if (staticProps) _defineProperties(Constructor, staticProps);
  Object.defineProperty(Constructor, "prototype", { writable: false });
  return Constructor; 
}
function _classPrivateMethodGet(receiver, privateSet, fn) { 
  if (!privateSet.has(receiver)) { 
    throw new TypeError("attempted to get private field on non-instance"); 
  } 
  return fn; 
}
  • 總結(jié)這部分代碼:public的屬性會(huì)定義在實(shí)例自身上,public的方法會(huì)定義在構(gòu)造器的prototype身上;static的屬性和方法都會(huì)定義在類自身上。

那么繼承是怎么實(shí)現(xiàn)的?

var Child = function(_Parent2) {
  _inherits(Child, _Parent2);
  function Child(name) {
    var _this;
    _this = _callSuper(this, Child);
    _this.name = name;
    return _this;
  }
  _createClass(Child, [{
    key: "speakName",
    value: function speakName() {
      _get(_getPrototypeOf(Child.prototype), "speakName", this).call(this);
    }
  }]);
  return Child; 
}(Parent);

function _inherits(subClass, superClass) {
  if (typeof superClass !== "function" && superClass !== null) {
    throw new TypeError("Super expression must either be null or a function");
  }
  subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } });
  Object.defineProperty(subClass, "prototype", { writable: false });
  if (superClass) _setPrototypeOf(subClass, superClass); 
}
function _setPrototypeOf(o, p) { 
  _setPrototypeOf = Object.setPrototypeOf ?
    Object.setPrototypeOf.bind() :
    function _setPrototypeOf(o, p) { o.__proto__ = p; return o; };
  return _setPrototypeOf(o, p);
}
function _callSuper(t, o, e) {
  return o = 
    _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? 
      Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) :
      o.apply(t, e)); 
}

  • 總結(jié)這部分代碼:繼承是通過修改子類的prototype指向了一個(gè)新對(duì)象,新對(duì)象的prototype指向了父類的prototype,且新對(duì)象的constructor保持子類的constructor不變且允許外部代碼修改。然后將子類的prototype拒絕被賦值為其他對(duì)象。最后將子類的__proto__指向父類。
  • 有個(gè)問題,為什么要?jiǎng)?chuàng)建一個(gè)新對(duì)象而不是讓子類的prototype直接指向父類的prototype呢?這是因?yàn)樵谥按a中給子類prototype添加公開方法的時(shí)候避免影響父類。
  • 還有一個(gè)問題,為什么需要__proto__指向父類呢?這是為了靜態(tài)屬性和方法也能讓子類調(diào)用到父類的,前面也提到了靜態(tài)的方法和屬性都是掛載到類自身。

拓展:原型鏈

  • 每個(gè)對(duì)象(數(shù)組、函數(shù)等)都有__proto__屬性,通過該屬性指向其他對(duì)象串聯(lián)出原型鏈
  • 函數(shù)不僅僅有__proto__還有prototype,但是尋找原型鏈并不會(huì)經(jīng)過prototype,除非你是new了一個(gè)類,因?yàn)閚ew關(guān)鍵字將類的prototype作為實(shí)例__proto__的值了。

例子

  • 例一
function P() {}
P.prototype.x = 'x'

function C() {}
C.prototype = P.prototype
console.log(C.x) // undefined
  • 例二
function P() {}
P.prototype.x = 'x'
P.x = 'xxx'

function C() {}
C.__proto__ = P;
console.log(C.x)  // xxx

以上就是詳解babel是如何將class語法糖轉(zhuǎn)換為es5的語法的詳細(xì)內(nèi)容,更多關(guān)于babel class轉(zhuǎn)換為es5的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論