为什么不提升ES6课程?

Pet*_*ler 55 javascript ecmascript-6

由于ES6类只是JavaScript现有的基于原型的继承 [1]语法糖,因此(IMO)提升它的定义是有道理的:

var foo = new Foo(1, 2); //this works

function Foo(x, y) {
   this.x = x;
   this.y = y;
}
Run Code Online (Sandbox Code Playgroud)

但以下方法不起作用:

var foo = new Foo(1, 2); //ReferenceError

class Foo {
   constructor(x, y) {
      this.x = x;
      this.y = y;
   }
}
Run Code Online (Sandbox Code Playgroud)

为什么不提升ES6课程?

Ber*_*rgi 53

为什么不提升ES6课程?

其实他们悬挂(变量绑定在整个范围内都有效),只是想letconst -他们只未初始化.

提升其定义是有意义的

不.在定义之前使用类永远不是一个好主意.考虑这个例子

var foo = new Bar(); // this appears to work
console.log(foo.x)   // but doesn't

function Bar(x) {
    this.x = x || Bar.defaultX;
}
Bar.defaultX = 0;
Run Code Online (Sandbox Code Playgroud)

并将其与之比较

var foo = new Bar(); // ReferenceError
console.log(foo.x);

class Bar {
    constructor (x = Bar.defaultX) {
        this.x = x;
    }
}
Bar.defaultX = 0;
Run Code Online (Sandbox Code Playgroud)

它会像你期望的那样抛出一个错误.这是静态属性,原型mixins,装饰器和一切的问题.对于子类化来说非常重要,当你使用带有非调整原型的类时,它完全在ES5中破坏,但是如果extended类尚未初始化,现在会抛出错误.


Oli*_*eke 15

虽然非提升类(在某种意义上,它们的行为类似于let绑定)可以被认为是更可取的,因为它们导致更安全的使用(请参阅Bergi 的回答),但在2ality博客上找到的以下解释似乎提供了一个稍微更基本的原因执行:

这种限制 [非提升] 的原因是类可以有一个extends子句,其值为任意表达式。该表达式必须在适当的“位置”中求值,它的求值不能被提升。


小智 9

在 Javascript 中,所有声明(var、let、const、function、function*、class)都会被提升,但应该在相同的作用域中声明。

正如您所说“ES6 类只是 JavaScript 现有的基于原型的继承的语法糖”

那么让我们了解一下它是什么?

这里你声明了一个实际上是“特殊函数”的类。让我们假设你的函数 Foo() 和类 Foo 都在全局范围内。

class Foo {
   constructor(x, y) {
      this.x = x;
      this.y = y;
   }
}
Run Code Online (Sandbox Code Playgroud)

以下是 Foo 类的编译代码。

var Foo = (function () {
    function Foo(x, y) {
        this.x = x;
        this.y = y;
    }
    return Foo;
}());
Run Code Online (Sandbox Code Playgroud)

在内部,您的类在包装函数(iife)内转换为具有相同名称的函数,并且该包装函数返回您的函数。

因为你的函数(类)范围改变了。并且您正在尝试在全局范围内创建实际上不存在的函数对象。

一旦编译完成,您就可以在变量 Foo 中获得该函数。所以稍后你在 var 中有函数,你可以创建它的对象。

  • 如果你使用像 babel 这样的东西,是的。但本身支持类的环境不会这样做。 (3认同)