ES6(ECMAScript 6)是即将到来的新版本JavaScript语言的标准,代号harmony(和谐之意,显然没有跟上我国的步伐,我们已经进入中国梦版本了)。上一次标准的制订还是2009年出台的ES5。目前ES6的标准化工作正在进行中,预计会在14年12月份放出正式敲定的版本。但大部分标准已经就绪,且各浏览器对ES6的支持也正在实现中。
ES6中定义类的方式, 就是ES3和ES5中定义类的语法糖,虽然也有些区别,但是整体定义类的方式更加简洁,类的继承更加方便, 如果想对ES6中的继承更加熟悉, 最好了解ES5中原型继承的方式, 博客园中说JS继承的文章很多, 想要深入了解的同学自己去搜;
定义一个class:
每一个使用class方式定义的类默认都有一个constructor函数, 这个函数是构造函数的主函数, 该函数体内部的this指向生成的实例, say() {}为原型上的方法, 我们定义一个简单的类 :
运行下面代码
"use strict"; class Person { constructor(name) { this.name = name; } say () { console.log("say hi"); } }; new Person().say(); //控制台会输出say hi
注意: ES6中声明的类不存在函数声明提前的问题, 类必须先声明再使用,否则会出现异常 , 我们只是把上面Demo中的代码位置一改, 立马报错, (如果用ES5中的思维去理解的话, 声明的类没有声明提前, 有关声明提前的知识点, 通过class 类名{} 声明的类,就是var 类名 = function(){});
运行下面代码
"use strict"; new Person().say(); class Person { constructor(name) { this.name = name; } say () { console.log("say hi"); } };
定义函数的静态方法:
如果定义函数的时候, 大括号内部, 函数名前声明了static, 那么这个函数就为静态函数, 就为静态方法, 和原型没啥关系:
运行下面代码
"use strict"; class Person { constructor(name) { this.name = name; } static say () { console.log("say hi"); } }; Person.say();
定义原型方法:
定义原型方法,直接这样声明: 函数名 () {} 即可, 小括号内部为参数列表, 大括号内部为代码块, ES5中要定义原型方法是通过: 构造函数.prototype.原型方法名() {} , 这种书写形式很繁琐, 使用ES6定义原型的方式有点像java和C#了, 这些都是比较高级语言的特征:
运行下面代码
"use strict"; class Person { constructor(name) { this.name = name; } say () { console.log("say hi"); } sing () { console.log("lalalalala"); } }; new Person().say(); //输出 :say hi new Person().sing(); //输出 :lalalalala
静态属性和原型属性:
只能在类定义完毕以后再定义静态属性,有点坑爹, 语言作者实现这种方式可能是为了避免代码的混乱, 所有的静态属性在同一个地方定义, 代码回更加规范?
运行下面代码
"use strict"; class Person { constructor(name) { this.name = name; } }; Person.hands = 2; console.log(Person.hands);
原型上面也不能定义属性了, 我们只能在原型上定义set和get, 取值和设值器, 要注意取值器和设值器是在原型上....:
运行下面代码
class Person { constructor(_name) { this._name = _name; } get name() { return this._name; } set name(_name) { this._name = _name; } } var p = new Person(); p.name = "heheda"; console.log(p.name); //输出:heheda console.log(p._name); //输出:heheda
如果要定义原型属性的话, 直接把属性定义在constructor内部即可, 如果是继承的话, 子类也会继承父类的这个属性:
运行下面代码
class Person { constructor() { this.name = "default"; } } class Man extends Person{ constructor() { super(); } } console.log( new Man().name );
类的继承extends:
ES5已经有继承, 但是这种继承经常绕来绕去的, ES6的继承也只是基于原型继承的封装(语法糖), 虽然的确简洁了不少, 还是java的继承比较好学啊, 下面Demo的例子中的SMan是超人的意思,别想歪了;
运行下面代码
"use strict"; class Person { constructor(name) { this.name = name; } say () { console.log("say hi"); return this; } }; class SMan extends Person { constructor (name, power) { super(name); this.superPower = power; } show () { console.log(this.superPower); return this; } } console.log( new SMan("Clark", "pee").show().say().name ); //输出: pee say hi Clark
如果要使用继承的话, 在子类中必须执行super()调用父类, 否者编译器会抛错, 在子类中的super有三种作用, 第一是作为构造函数直接调用,第二种是作为父类实例, 第三种是在子类中的静态方法中调用父类的静态方法;
ES6继承的和ES5继承的主要区别, ES5中常用的继承是把子类的原型设置为父类的实例, 子类自然就有了父类的所有方法和属性:
运行下面代码
var Sup = function() { this.sub = true; }; Sup.prototype.protoSup = {sup:"sup"}; var Sub = function() { this.sub = true; }; Sub.prototype = new Sup(); //继承原型; Sub.prototype.constructor = Sub; //修正constructor;
而在ES6中实现的继承更加精巧, 不会有受到父类的干扰, 这种继承是结合了apply继承和原型继承实现的组合继承:
运行下面代码
var Sup = function() { this.sub = true; }; var Sub = function() { this.sup = true; Sup.apply(this); //继承this的属性和方法; }; Sub.__proto__ = Sup; //继承Sup静态属性; Sub.prototype = Object.create( Sup.prototype, {constructor : { value: Sub, enumerable: false, writable: true, configurable: true }}); //继承原型属性,并覆写constructor;
用图片可以比较容易看出两者区别, 图示ES5和ES6继承的区别:http://keenwon.com/1524.html ;
ES5模拟ES6的继承:
因为有了转码器babel , 我们能通过ES5的代码, 去窥探ES6的继承到底是怎么实现, ES6的继承:
运行下面代码
"use strict"; class Person { constructor(name) { this.name = name; } say () { console.log("say hi"); return this; } }; class SMan extends Person { constructor (name, power) { super(name); this.superPower = power; } show () { console.log(this.superPower); return this; } } console.log( new SMan("Clark", "pee").show().say().name );
使用babel转化为ES5以后, 代码变成这样了, 我自己加了一点注释, 原谅我放荡不羁爱自由..:
运行下面代码
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 _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 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") "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } //继承父类的原型,并修正constructor为子类; subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); //又给子类这个对象定义__proto__ 为父类, 这样能够实现静态属性继承; if (superClass) Object.setPrototypeOf "say", value: function say() { console.log("say hi"); return this; } }]); return Person; }(); ; var SMan = function (_Person) { _inherits(SMan, _Person); function SMan(name, power) { //此时的this.__proto__已经指向 构造函数的prototyp了 _classCallCheck(this, SMan); //这句话相当于是ES6中的super(), 把父类的属性通过call, 执行继承; var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(SMan).call(this, name)); _this.superPower = power; //动态返回_this; return _this; } _createClass(SMan, [{ key: "show", value: function show() { console.log(this.superPower); return this; } }]); return SMan; }(Person); console.log(new SMan("Clark", "pee").show().say().name);
多重继承:
使用mix-in, 实现多重继承, 书写方式为:class Sub extends mix(obj0, obj1, obj2) , mix只是一个方法 ,这个方法我们要自己去定义:
运行下面代码
<html> <head> <meta charset="utf-8"> </head> <body> <script> "use strict"; function mix(...mixins) { class Mix {} for (let mixin of mixins) { copyProperties(Mix, mixin); copyProperties(Mix.prototype, mixin.prototype); } return Mix; } function copyProperties(target, source) { for (let key of Reflect.ownKeys(source)) { if ( key !== "constructor" && key !== "prototype" && key !== "name" ) { let desc = Object.getOwnPropertyDescriptor(source, key); Object.defineProperty(target, key, desc); } } } class Man{ work () { console.log("working"); } } class Woman{ say () { console.log("saying"); } } class SuperMan extends mix(Man, Woman) { constructor () { super(); } } var sm = new SuperMan(); sm.work(); sm.say(); //实际上它们不存在继承关系, 只是把属性复制到子类上; console.log(sm instanceof Man); console.log(sm instanceof Woman); </script> </body> </html>
以上所述是小编给大家介绍的JavaScript ES6的新特性使用新方法定义Class的相关知识,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]