【探秘ES6】系列专栏（十一）：类语法

发表于2015-08-14 16:05| 次阅读| 来源Mozilla Web开发者博客| 0 条评论| 作者Eric Faust

ES6作为新一代JavaScript标准，已正式与广大前端开发者见面。为了让大家对ES6的诸多新特性有更深入的了解，Mozilla Web开发者博客推出了《ES6 In Depth》系列文章。CSDN已获授权，将持续对该系列进行翻译，组织成【探秘ES6】系列专栏，供大家学习借鉴。本文为该系列的第十一篇。

• 为给定的Canvas画一个Circle。
• 记录所画Circle的个数。
• 记录给定Circle的半径，以及如何给不变量（invariant）强行赋值。
• 计算给定Circle的面积。

```function Circle(radius) {
}

Circle.draw = function draw(circle, canvas) { /* Canvas drawing code */ }

get: function() {
return !this._count ? 0 : this._count;
},

set: function(val) {
this._count = val;
}
});

Circle.prototype = {
area: function area() {
}
};

get: function() {
},

throw new Error("Circle radius must be an integer.");
}
});```

1. 给对象添加普通函数（normal function）。
2. 给对象添加生成器函数（generator function）。
3. 给对象添加普通访问器函数属性（accessor function property）。
4. 给已创建的对象添加上述任何函数，好像使用方括号［］语法就能完成的样子。我们称之为计算属性名（computed property name）。

```var obj = {
// Methods are now added without a function keyword, using the name of the
// property as the name of the function.
method(args) { ... },

// To make a method that's a generator instead, just add a '*', as normal.
*genMethod(args) { ... },

// Accessors can now go inline, with the help of |get| and |set|. You can
// just define the functions inline. No generators, though.

// Note that a getter installed this way must have no arguments
get propName() { ... },

// Note that a setter installed this way must have exactly one argument
set propName(arg) { ... },

// To handle case (4) above, [] syntax is now allowed anywhere a name would
// have gone! This can use symbols, call functions, concatenate strings, or
// any other expression that evaluates to a property id. Though I've shown
// it here as a method, this syntax also works for accessors or generators.
[functionThatReturnsPropertyName()] (args) { ... }
};```

```function Circle(radius) {
}

Circle.draw = function draw(circle, canvas) { /* Canvas drawing code */ }

get: function() {
return !this._count ? 0 : this._count;
},

set: function(val) {
this._count = val;
}
});

Circle.prototype = {
area() {
},

},
throw new Error("Circle radius must be an integer.");
}
};```

```class Circle {
};

static draw(circle, canvas) {
// Canvas drawing code
};

return !this._count ? 0 : this._count;
};
this._count = val;
};

area() {
};

};
throw new Error("Circle radius must be an integer.");
};
}```

• 分号用来做什么？为了“让一切看起来更像传统的类”，我们决定使用更为传统的分隔符。不喜欢它吗？这是可选的，分隔符并不是必须的。
• 如果我不想要构造函数，但仍然想给已创建的对象添加方法该怎么办？很好！constructor方法完全是可选的。如果不这样做，默认情况就像已经敲了constructor() {}。
• “constructor”可以是生成器吗？不可以！使用非普通方法（normal method）添加constructor会导致TypeError，包括生成器和访问器。
• 可以使用计算属性名定义constructor吗？遗憾的是不可以。这将非常难以被探测。因此我们就不试了。如果使用计算属性名定义方法的话，最终方法会被命名为“constructor”，仍会得到一个名为 constructor的方法，而不是类的构造函数。
• 好吧，但是我可以直接传入对象字面量作为函数的参数。使用新语法定义的类看起来行不通了。很幸运，ES6还增加了类表达式！可以对其命名或者匿名。除了在声明它们的范围内不会创建变量，其行为与上面描述的函数完全相同。
• 上面的这些把戏如果是可枚举的，或者有什么其他性质会怎么样？这样做是为了可以给对象配置方法，但是当你对对象的属性进行枚举的时候，仅得到了已经添加进对象的数据属性。因为这是合理的，所以类里所配置的方法是configurable的，但不是enumerable的。
• 喂，等等……实例变量在哪里？static常量呢？好问题！在ES6中，类的定义目前不存在实例变量和静态常量。不过好消息是，连同参与其他规范的过程中，我都强有力地支持在类的语法中设有static和const值。事实上，这已经出现在了规范相关的会议上。我想可以期待以后出现更多与此有关的讨论。
• 好吧，即便如此，这些也都是极好的！我可以使用它们了吗？不完全可以。有那些可选用的polyfill（特别是Babel）存在，你可以试着使用它们。遗憾的是，在被主流浏览器原生地实现以前，还需要一些时间。我们这里讨论的一切都在Nightly版的Firefox浏览器实现过。Edge和Chrome浏览器也实现了，但是默认情况下并未被启用。还有个遗憾就是Safari浏览器还没实现这些新特性。
• Java和C++都使用子类和super关键字，但这里并没提到，JS有相关概念吗？有的！但这完全是一个值得另外成文讨论的事情。回头再看我们今后有关使用子类的更新，将讨论更多有关JavaScript中类的威力。

• CSDN官方微信
• 扫描二维码,向CSDN吐槽
• 微信号：CSDNnews