Babel.js如何创建编译ES2015的类声明?

时间:2016-03-03 14:29:45

标签: javascript class compilation babeljs

我目前的任务是将JavaScript组件ES5转换为ES6(使用Babel.js编译)。在使用类和Babel.js之前,我们使用原型来从其他组件中获取函数。

com.company.js.ComponentA.prototype = new com.company.js.utils.UltraFunctions()

现在使用Babel.js并将ComponentA转换为类

class ComponentA {
  contructor(){
    this.property = "Proppy";
  }
  doStuff() {
    console.log("doStuff");
  }
}

现在,当我在实例化它之后分析这个组件时会发生什么,现在我看到了两个级别的原型。第一个原型保存“属性” - 第二个原型嵌套在第一个原型中,在这种情况下保存所有功能“doStuff”。这带来了遗留组件的问题,这些组件不应该转换为类(尚未)。因为这些组件是通过二级原型放入的,所以它们会覆盖原型,该原型包含Babel.js编译的“合成”类的功能。

我不是要求解决方案。我只是想确定Babel.js将类转换为ES5 JavaScript的假设是否正确。特别是如上所述创建两级原型的事实。

更新

对不起,我很清楚第一个原型!正如@ T.J.Crowder在评论中所说的那样,第一个是实例 - 因此“属性”被粉碎到实例中,而函数通过原型插入到“第一”级原型中。所以,用第二级替换我说的第一级和第一级到实例。

2 个答案:

答案 0 :(得分:14)

  

我只想讨论Babel.js如何将类转换为ES5 Javascript。

Babel使用了很多辅助函数,或者我会说“只看看已转换的结果”。 : - )

使用ES2015,它是一个非常简单的映射,因为class语法故意保留为第一个版本的基本(ES2016将扩展它,但提案并没有完全成功,所以他们会稍后,可能是ES2017)。

class允许我们定义:

  • 构造函数(通过classconstructor
  • 构造函数的prototype对象的原型(通过extends
  • 放置构造函数的prototype对象
  • 的方法
  • 构建函数本身(static
  • 的方法
  • 一种简洁,便携地引用基础“类”构造函数及其原型信息的方法

所以这个:

// Base "class":
class Base {
    // The code for `Base` goes in this special `constructor` pseudo-method:
    constructor() {
        this.baseProp = 42;
    }

    // A method to put on the `prototype` object (an "instance method"):
    baseMethod() {
        console.log(this.baseProp);
    }

    // A method to put on the constructor (a "static method"):
    static foo() {
        console.log("This is foo");
    }
}

// Derived "class":
class Derived extends Base {
//            ^------------------ defines the prototype behind `Derived.prototype`
    // The code for `Derived`:
    constructor() {
        // Call super constructor (`Base`) to initialize `Base`'s stuff:
        super();

        // Properties to initialize when called:
        this.derivedProp = "the answer";
    }

    // Overridden instance method:
    baseMethod() {
        // Supercall to `baseMethod`:
        super.baseMethod();

        // ...
        console.log("new stuff");
    }

    // Another instance method:
    derivedMethod() {
        this.baseMethod();
        console.log(this.derivedProp);
    }
}

成为我们在ES5中编写的内容(如果我们没有使用任何辅助函数),就像这样:

// This combines the name defined by `class` with the code defined in `constructor`:
var Base = function() {
    this.baseProp = 42;
};
// The "instance" method:
Base.prototype.baseMethod = function() {
    console.log(this.baseProp);
};
// The "static" method:
Base.foo = function() {
    console.log("This is foo");
};

// The derived constructor
var Derived = function() {
    // Call super constructor (`Base`) to initialize `Base`'s stuff:
    Base.call(this);

    // Properties to add when called:
    this.derivedProp = "the answer";
};

// This was done by `class` and `extends`:
Derived.prototype = Object.create(Base.prototype);
Derived.prototype.constructor = Derived;

// Overridden instance method:
Derived.prototype.baseMethod = function() {
    // Supercall to `baseMethod`:
    Base.prototype.baseMethod.call(this);

    // ...
    console.log(this.derivedProp);
};

// Another instance method:
Derived.prototype.derivedMethod = function() {
    this.baseMethod();
    console.log(this.derivedProp);
};

以上注意事项:

  • constructor成为构造函数
  • 所有非constructor,非static方法都成为原型方法
  • static方法分配给构造函数
  • 上的属性
  • 属性就像往常一样
  • 创建要派生构造函数的prototype属性的对象是通过Object.create(Base.prototype) new Base()完成的。
  • constructor将基础构造函数作为其第一个操作。
  • 调用ES5版本中的super方法(Base.prototype.baseMethod.call(this);)既麻烦又容易出错,这是新语法的一大优点

答案 1 :(得分:3)

ES6 / Babel类语法复制了与使用函数构造函数和覆盖原型时相同的原型模式。一旦调用构造函数,下面的示例将生成相同的实例对象。

ES6 /巴贝尔

class ComponentA {
      constructor(){
        this.property = "Proppy";
      }
      doStuff() {
        console.log("doStuff");
      }
    }

var c = new ComponentA();

ES5

var ComponentA = function () {
  this.property = "Proppy";
}

ComponentA.prototype.doStuff = function () {
  console.log("doStuff");
}

var c = new ComponentA();

下面是如何在ES6类语法和ES5中继承另一个构造函数原型的示例。

ES6 /巴贝尔

class Parent {
  constructor(){
    this.property = "Proppy";
  }
  doStuff() {
    console.log("doStuff");
  }
}

class ComponentA extends Parent {
  constructor() {
    super();
  }
}

var c = new ComponentA();

ES5

var Parent = function () {
    this.property = "Proppy";
}

Parent.prototype.doStuff = function () {
    console.log("doStuff");
}

function ComponentA () {
  Parent.call(this);
}

ComponentA.prototype = Object.create(Parent.prototype);
ComponentA.prototype.constructor = ComponentA;

var c = new ComponentA();

在您给出的示例中,您的ComponentA不会以相同的方式继承UltraFunctions()的原型,因为您在覆盖它之后没有将ComponentA.prototype.constructor重置回ComponentA函数。原型。

结果是一个ComponentA实例对象,它实际上不是ComponentA的一个实例,而是一个由ComponentA构造函数变异的UltraFunctions()实例。

您可能会有一些负面结果,因为一些Object.prototype方法(如.hasOwnProptery)在迁移组件以使用类语法时不会像以前那样工作。

你的例子的另一个问题是"构造函数"拼写错误。这会导致Babel的结果与您的预期不同。