Javascript新标准ES6正式出来都一年多了,最近才有时间愿意集中精力研究下,发现有些新特性确实亮瞎了我的双眼,比如,最新的“类-实例”的支持,再比如模仿Python引入gennerator等等。下面和大家分享下我ES6类继承的学习笔记吧。
JavaScript的标准——ECMAScript在不断发展,最新版ECMAScript 2015标准(简称ES6)已经在2015年6月正式发布了。新版本的ES有很多亮点,其中一个亮点就是正式引入了class关键字,开始正式支持面向对象的“类-实例”方式了。
以前JavaScript的对象模型是基于原型实现的,特点是简单,缺点是理解起来比传统的“类-实例”模型要困难,最大的缺点是继承的实现需要编写大量代码,并且需要正确实现原型链。
下面是利用原型实现类继承的一种方式:
'use strict';
//动物原型
function Animal(props){
this.name=props.name||"未知";
}
Animal.prototype.eat=function(){
alert(this.name+"在吃东西...");
}
//继承动物的鸟
function Bird(props){
Animal.call(this,props);
this.type=props.type||”未知”;
}
function F(){}
F.prototype=Animal.prototype;
Bird.prototype=new F();
Bird.prototype.constructor=Bird;
Bird.prototype.fly=function(){
alert(this.name+"在飞...");
}
效果如下:
可见,为了实现类的继承,使用了中间量等大量辅助代码,废了多大功夫,不熟悉的人还不大理解。庆幸的是在ES6中,终于有了类似C++/PHP等语言那种真正意义上的“类-实例”模型了:
'use strict';
class Animal{
//构造函数
constructor(props){
this.name=props.name||'未知';
}
eat(){
alert(this.name+"在吃东西...");
}
}
//class继承
class Bird extends Animal{
//构造函数
constructor(props){
//调用实现父类的构造函数
super(props);
this.type=props.type||"未知";
}
fly(){
alert(this.name+"在飞...");
}
}
效果如下:
效果一样,但是是不是瞬间有种回到PHP代码的赶脚??看起来还是那么熟悉的姿势。嘿嘿。。。
ES6中的class用起来是蛮爽的,但是,由于出来的比较晚了,不是所有的主流浏览器都支持ES6滴,况且不少童鞋还在用IE6呢,那么岂不是咱写代码时不敢用啦?幸运的是有个Babel的工具,可以实现自动从ES6转换为ES5。具体安装和使用有篇博客写的不错,可以参考下:Babel安装
,其实还可以直接用在线方式实现代码的装换(Babel在线转换):
上面ES6代码转换的结果如下:
'use strict';
var _createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
function _possibleConstructorReturn(self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && (typeof call === "object" || typeof call === "function") ? call : self;
}
function _inherits(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
var Animal = function () {
//构造函数
function Animal(props) {
_classCallCheck(this, Animal);
this.name = props.name || '未知';
}
_createClass(Animal, [
{
key: 'eat',
value: function eat() {
alert(this.name + "在吃东西...");
}
}
]);
return Animal;
}();
//class继承
var Bird = function (_Animal) {
_inherits(Bird, _Animal);
//构造函数
function Bird(props) {
_classCallCheck(this, Bird);
var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(Bird).call(this, props));
_this.type = props.type || "未知";
return _this;
}
_createClass(Bird, [
{
key: 'fly',
value: function fly() {
alert(this.name + "在飞...");
}
}
]);
return Bird;
}(Animal);
是不是又回到了基于原型实现的时代?这段代码就可以被一些老的浏览器支持了。
现在,我们写javascript代码的时候,可以用一些ES6的新特性,比如class类继承等,然后再转换为ES5的标准,保证对一些老浏览器的兼容性。