by Mariya Diminsky
通过玛丽亚·迪明斯基(Mariya Diminsky)
了解ES6 The Dope Way第五部分:类,转译ES6代码和更多资源! (Learn ES6 The Dope Way Part V: Classes, Transpiling ES6 Code & More Resources!)
Welcome to Part V of Learn ES6 The Dope Way, a series created to help you easily understand ES6 (ECMAScript 6)!
欢迎来到学习ES6 The Dope Way的第五部分,该系列旨在帮助您轻松理解ES6(ECMAScript 6)!
Today we’ll explore ES6 classes, learn how to compile our code into ES5 for browser compatibility and learn about some awesome resources that will help us understand ES6 in greater depth! Adventure time! ❤
今天,我们将探索ES6 类 ,学习如何将代码编译到ES5中以实现浏览器兼容性,并了解一些很棒的资源,这些资源将帮助我们更深入地了解ES6! 冒险时间! ❤
ES6中的类 (Classes in ES6)
Benefits:
好处:
- A simpler way of dealing with JavaScript’s Prototype-Inheritance — it’s just ‘syntactical sugar’. 处理JavaScript的原型继承的一种更简单的方法-只是“语法糖”。
- You are still using the same object-oriented inheritance model. 您仍在使用相同的面向对象的继承模型。
Similar to class syntax in Java, Python, Ruby and PHP.
类似于Java,Python,Ruby和PHP中的类语法。
- Saves you a lot of typing. 为您节省很多打字时间。
Beware:
谨防:
Use can only invoke a class via new, not a function call.
使用只能通过新的 ,而不是一个函数调用调用的类 。
Use super() to call the constructor of a parent class.
使用super()调用父类的构造函数 。
A class looks like an object but behaves like a function — because it is a function.
一个类看起来像一个对象,但是表现得像一个函数,因为它是一个函数。
Class declarations are not hoisted as function declarations are.
没有像函数声明那样悬挂类声明。
A name given to a class expression is only local to the class body.
给类表达式指定的名称仅在类主体中是局部的。
A SyntaxError will be thrown if the class contains more than one occurrence of a constructor method.
如果该类包含多次构造函数方法,则将引发SyntaxError 。
While the members of an object literal are separated by commas, commas are illegal in classes — this emphasizes the difference between them. Semicolons are only allowed for future syntax (possibly ES7), which may include properties cancelled by semicolons.
尽管对象文字的成员之间用逗号分隔,但逗号在类中是非法的-这强调了它们之间的区别。 仅允许分号用于将来的语法(可能是ES7),其中可能包括分号取消的属性。
In derived classes(explained later), super() must be called first, before you can use the this keyword. Otherwise it will cause a ReferenceError.
在派生类 (稍后说明)中,必须先调用super() ,然后才能使用this关键字。 否则会导致ReferenceError 。
Static properties are properties of the class itself. Thus while they can be inherited and accessed by directly calling the class name, if you call an instance of the class(and store it within a variable) you will not be able to access it with that variable.
静态属性是类本身的属性。 因此,尽管可以通过直接调用类名来继承和访问它们,但是如果您调用类的实例(并将其存储在变量中) 您将无法使用该变量进行访问。
建立课程 (Creating a Class)
So how do we create a class? Let us first review how objects are created in ES5 without the use of classes:
那么我们如何创建一个类呢? 让我们首先回顾一下如何在ES5中创建对象而不使用类 :
function Bunny(name, age, favoriteFood) {
this.name = name;
this.age = age;
this.favoriteFood = favoriteFood;
}
Bunny.prototype.eatFavFood = function () {
console.log('\"Mmmm! Those ' + this.favoriteFood + ' were delicious\", said ' + this.name + ', the ' + this.age + ' year old bunny.');
};
var newBunny = new Bunny('Brigadier Fluffkins', 3, 'Raspberry Leaves');
newBunny.eatFavFood();
// "Mmmm! Those Raspberry Leaves were delicious", said Brigadier Fluffkins, the 3 year old bunny.
Now observe the same thing with ES6 classes:
现在使用ES6 类观察相同的事情:
class Bunny {
constructor(name, age, favoriteFood){
this.name = name;
this.age = age;
this.favoriteFood = favoriteFood;
}
eatFavFood() {
console.log(`"Mmmm! Those ${this.favoriteFood} were delicious", said ${this.name} the ${this.age} year old bunny.`);
};
}
let es6Bunny = new Bunny('Brigadier Fluffkins', 3, 'Raspberry Leaves');
es6Bunny.eatFavFood();
// "Mmmm! Those Raspberry Leaves were delicious", said Brigadier Fluffkins the 3 year old bunny.
What are the main differences? Clearly the class syntax looks like an object, but remember that actually it’s still a function and behaves so. Test it out yourself:
主要区别是什么? 显然, 类语法看起来像一个对象,但是请记住,实际上它仍然是一个函数并且行为如此。 自己测试一下:
typeof Bunny
// function
Another main difference is anything you want to store must be within a constructor method. Any prototype method of the class should be inside of that class, but outside of the constructor, without writing ‘.prototype’, and in ES6 function syntax.
另一个主要区别是,要存储的任何内容都必须在构造函数方法内。 该类的任何原型方法都应在该类的内部,但应在构造函数的外部,而无需编写'。 原型 ”,并采用ES6函数语法。
定义类和原型继承的两种方式 (Twos Ways of Defining a Class & Prototype Inheritance)
Now there are two main ways of defining a class — the example above is one of the more common ways, a class declaration. While a class is indeed a function and function declarations are hoisted — meaning the function can be accessed no matter if it is called before it is declared — yet you cannot hoist a class declaration. This is important to remember:
现在有两种定义类的主要方法-上面的示例是一种较常见的方法,即类声明。 虽然类确实是一个函数,并且函数声明已被悬挂(这意味着该函数可以在声明前被调用,无论它是否被调用)都可以访问,但是您不能悬挂一个类声明。 重要的是要记住:
// Normal function declaration
// called before it is declared and it works.
callMe(); // Testing, Testing.
function callMe() {
console.log("Testing, Testing.")
}
// This is called after, as we would do in a function expression,
// and it works too!
callMe() // Testing, Testing.
// But with classes...You can't create an instance of a class
// before creating it:
let es6Bunny = new Bunny('Brigadier Fluffkins', 3, 'Raspberry Leaves');
es6Bunny.eatFavFood();
class Bunny {
constructor(name, age, favoriteFood){
this.name = name;
this.age = age;
this.favoriteFood = favoriteFood;
}
eatFavFood() {
console.log(`"Mmmm! Those ${this.favoriteFood} were delicious", said ${this.name} the ${this.age} year old bunny.`);
};
}
// Instead we get this: Uncaught ReferenceError: Bunny is not defined
The reason for this limitation is that classes can have an extends clause — used for inheritance — whose value can be specified at a later time or may even depend on an inputted value or computation. Since expressions may sometime need to be evaluated another time, it makes sense for this evaluation not to be hoisted before all values are evaluated. Not doing so may cause errors in your code.
这种限制的原因是, 类可以具有用于继承的扩展子句,其子句的值可以在以后指定,甚至可以取决于输入的值或计算。 由于有时可能需要再次评估表达式,因此在评估所有值之前不要取消此评估是有意义的。 否则可能会导致代码错误。
Still, it is possible to store an instance of a class before it is created in a function for later use and evaluate it after the class has been defined:
尽管如此,仍然可以在创建一个类的实例之前将其存储在函数中以供以后使用,并在定义该类之后对其进行评估:
function createNewBunny() { new Bunny(); }
createNewBunny(); // ReferenceError
class Bunny {...etc}
createNewBunny(); // Works!
The second way to define a class is a class expression. As with function expressions, class expressions can be named or anonymous. Be aware, these names are only local to the class body and cannot be accessed outside of it:
定义类的第二种方法是类表达式。 与函数表达式一样,类表达式可以命名或匿名。 请注意,这些名称仅在类主体内部,不能在其外部访问:
// anonymous:
const Bunny = class {
etc...
};
const BunnyBurgerKins = new Bunny();
// named
const Bunny = class SurferBunny {
whatIsMyName() {
return SurferBunny.name;
}
};
const BunnyBurgerKins = new Bunny();
console.log(BunnyBurgerKins.whatIsMyName()); // SurferBunny
console.log(SurferBunny.name); // ReferenceError: SurferBunny is not defined
There are two types of classes: The base class — or the parent class — and the derived class — the inherited subclass. Here Bunny is the base class and BelgianHare is the derived class since it has the extends clause. Notice how simple the syntax for prototype inheritance is with classes:
有两种类型的类 :基类(或父类)和派生类(继承的子类)。 这里Bunny是基类,而BelgianHare是派生类,因为它具有extends子句。 请注意,使用类继承原型的语法非常简单:
class Bunny {
constructor(name, age, favoriteFood){
this.name = name;
this.age = age;
this.favoriteFood = favoriteFood;
}
eatFavFood() {
console.log(`"Mmmm! That ${this.favoriteFood} was delicious", said ${this.name} the ${this.age} year old bunny.`);
};
}
class BelgianHare extends Bunny {
constructor(favDrink, favoriteFood, name, age) {
super(name, age, favoriteFood);
this.favDrink = favDrink;
}
drinkFavDrink() {
console.log(`\"Thank you for the ${this.favDrink} and ${this.favoriteFood}!\", said ${this.name} the happy ${this.age} year old Belgian Hare bunny.`)
}
}
let newBelgHare = new BelgianHare('Water', 'Grass', 'Donald', 5);
newBelgHare.drinkFavDrink();
// "Thank you for the Water and Grass!", said Donald the happy 5 year old Belgian Hare bunny.
newBelgHare.eatFavFood();
// "Mmmm! That Grass was delicious", said Donald the 5 year old bunny.
The super() function inside of the derived class, BelgianHare, gives us access to the constructor in the base class, Bunny, so when we call the prototype methods from both classes(drinkFavDrink() from the derived class, and eatFavFood() from the base class), they both work!
派生类 BelgianHare内部的super()函数使我们可以访问基类 Bunny中的构造函数 ,因此,当我们从这两个类中调用原型方法时(派生类中的 drinkFavDrink()以及派生类中的 eatFavFood()基类 ),它们都可以工作!
浏览器兼容性 (Browser Compatibility)
Not all ES6 features are fully supported on all browsers as of yet. In the meantime stay updated by checking out these sites:
到目前为止,并非所有浏览器都完全支持所有ES6功能。 同时,通过查看以下站点来保持更新:
View compatibility chart: https://kangax.github.io/compat-table/es6/
查看兼容性图表: https : //kangax.github.io/compat-table/es6/
Enter any ES6 feature in manually: http://caniuse.com/#search=const
手动输入任何ES6功能: http : //caniuse.com/#search=const
转译ES6代码 (Transpiling ES6 Code)
Since not all browsers support all ES6 features you need to transpile your ES6 code into a compiler such as Babel or module bundler like Webpack.
由于并非所有浏览器都支持所有ES6功能,因此您需要将ES6代码转换为Babel等编译器或Webpack等模块捆绑器 。
Transpiling simply means taking out ES6 code and converting it into ES5 so it can be read by all browsers — like a safety precaution!
编译只是意味着取出ES6代码并将其转换为ES5,以便所有浏览器都可以读取它-就像安全预防措施一样!
There are many transpiling tools, the most popular are also the ones that support the most ES6 features:
有很多转码工具,最受欢迎的也是支持大多数ES6功能的工具:
Babel.js
Babel.js
Closure
关闭
Traceur
Traceur
You can use any of of these, but out of the three listed, I would recommend Babel for smaller projects. Please follow their simple steps for installing Babel into your project via Node: https://babeljs.io/
您可以使用其中的任何一个,但是在列出的三个中,我建议将Babel用于较小的项目。 请遵循他们通过Node将Babel安装到项目中的简单步骤: https : //babeljs.io/
For larger projects I recommend using Webpack. Webpack does a lot of complicated things for you, including: transpiling code, SAS conversions, dependency management, and even replacing tools such as Grunt, Gulp and Browserify. There is already an informative tutorial written on Webpack right over here.
对于较大的项目,我建议使用Webpack 。 Webpack为您完成了许多复杂的工作,包括:代码转换,SAS转换,依赖性管理,甚至替换了诸如Grunt , Gulp和Browserify之类的工具 。 已经有写的WebPack就在一个内容丰富的教程在这里 。
资源资源 (Resources)
Check out these resources to learn and explore ES6 in greater depth:
查阅以下资源,以更深入地学习和探索ES6:
The Mozilla Developer Network (MDN) is a superb tool for learning about all ES6 concepts, actually anything JavaScript. For example, let’s learn more about classes: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
Mozilla开发人员网络(MDN)是学习所有ES6概念(实际上是任何JavaScript)的绝佳工具。 例如,让我们了解有关类的更多信息: https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
Babel.js has super useful article summarizing all our ES6 points into one: https://babeljs.io/docs/learn-es2015/
Babel.js有一篇超级有用的文章,将我们所有的ES6点总结为一个: https ://babeljs.io/docs/learn-es2015/
This guy is always fun to watch: https://www.youtube.com/playlist?list=PL0zVEGEvSaeHJppaRLrqjeTPnCH6vw-sm
看着这个家伙总是很有趣: https : //www.youtube.com/playlist?list = PL0zVEGEvSaeHJppaRLrqjeTPnCH6vw-sm
And check out this exhaustive list of ES6 study resources: https://github.com/ericdouglas/ES6-Learning
并查看这份详尽的ES6研究资源清单: https : //github.com/ericdouglas/ES6-Learning
There are many, many more. Go forth my child, explore thy internet.
还有很多很多。 出来我的孩子,探索您的互联网。
Remember, no matter how experienced you are — Google is your friend.
请记住,无论您经验如何,Google都是您的朋友。
Congrats! You’ve made it through Learn ES6 The Dope Way Part V and now you’ve learned a clever way of using prototype inheritance through ES6 classes, understand that it’s important to always transpile your code since not all browsers support all features of ES6— either through Babel.js for smaller projects or Webpack for larger projects.
恭喜! 您已经通过学习ES6 The Dope Way Part V获得了成功,现在您已经了解了通过ES6 类使用原型继承的巧妙方法,要了解始终转换代码非常重要,因为并非所有浏览器都支持ES6的所有功能-通过Babel.js(适用于较小的项目)或Webpack(适用于较大的项目)。
Keep your wisdom updated by liking and following. This is the last lesson in the Learn ES6 The Dope Way series! Congrats, you’ve made it!! Pat yourself in the back you did a great job!! I’m so proud of you! Yay!!!
通过喜欢和关注来保持您的智慧更新。 这是Learn ES6 The Dope Way系列的最后一课! 恭喜,您做到了! 拍拍自己的背部,您做得很棒!! 我很为你骄傲! 好极了!!!
Thanks for reading ❤ Stay tuned for more JavaScript lessons underway!
感谢您阅读❤,敬请期待更多JavaScript课程!
Part II: (Arrow) => functions and ‘this’ keyword
Part III: Template Literals, Spread Operators & Generators!
Part IV: Default Parameters, Destructuring Assignment, and a new ES6 method!
Part V: Classes, Transpiling ES6 Code & More Resources!
You can also find me on github ❤ https://github.com/Mashadim
您也可以在github❤https ://github.com/Mashadim上找到我