为什么不提升ES6课程?

时间:2016-02-21 14:53:23

标签: 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;
}

但以下不会起作用:

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

class Foo {
   constructor(x, y) {
      this.x = x;
      this.y = y;
   }
}

为什么不提升ES6课程?

4 个答案:

答案 0 :(得分:50)

  

为什么不提升ES6课程?

实际上他们 被提升(变量绑定在整个范围内可用),就像let and const are一样 - 它们只是没有初始化。

  

提升其定义

是有意义的

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

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;

并将其与

进行比较
var foo = new Bar(); // ReferenceError
console.log(foo.x);

class Bar {
    constructor (x = Bar.defaultX) {
        this.x = x;
    }
}
Bar.defaultX = 0;

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

答案 1 :(得分:4)

在Javascript中,所有声明(var,let,const,function,function *,class)都悬挂,但应在相同范围中声明。

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

那么让我们理解它是什么?

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

class Foo {
   constructor(x, y) {
      this.x = x;
      this.y = y;
   }
}

以下是您的类Foo的编译代码。

var Foo = (function () {
    function Foo(x, y) {
        this.x = x;
        this.y = y;
    }
    return Foo;
}());

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

因为您的函数(类)范围已更改。并且您正试图在全局范围内创建功能对象,而实际上并不存在。

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

答案 2 :(得分:1)

虽然非悬挂类(在某种意义上表现得像let绑定)可以被认为是更可取的,因为它们会导致更安全的使用(请参见Bergi's answer),在{ {3}}博客似乎提供了此实现的一些更基本的原因:

  

此限制[非提升]的原因是,类可以具有一个extends子句,该子句的值可以是任意表达式。该表达式必须在正确的“位置”进行评估,其评估无法进行。

答案 3 :(得分:0)

类不会被提升,因为例如当一个类扩展一个表达式而不是一个函数时,就会发生错误:

 class Dog extends Animal {}
 var Animal = function Animal() {
 this.move = function () {
 alert(defaultMove);
 }
 }
var defaultMove = "moving";
var dog = new Dog();
dog.move();

吊装后会变成:

var Animal, defaultMove, dog;
class Dog extends Animal {}
Animal = function Animal() {
this.move = function () {
alert(defaultMove);
}
}
defaultMove = "moving";
dog = new Dog();
dog.move();

在Dog 扩展Animal 类被解释为Animal 实际上未定义的地方,我们得到一个错误。我们可以通过在 Dog 的声明之前移动 Animal 表达式来轻松解决这个问题。 请看这篇关于该主题的精彩文章: https://blog.thoughtram.io/angular/2015/09/03/forward-references-in-angular-2.html