博客园 首页 新随笔 联系 订阅
es6继承 vs js原生继承(es5)
最近在看es2015的一些语法,最实用的应该就是继承这个新特性了。比如下面的代码:
1 $(function(){
2 class Father{
3 constructor(name, age){
4 this.name = name;
5 this.age = age;
6 }
7
8 show(){
9 console.log(`我叫:${this.name}, 今年${this.age}岁`);
10 }
11 };
12 class Son extends Father{};
13
14 let son = new Son('金角大王', 200);
15 son.show();//return 我叫:金角大王, 今年200岁
16
17 });
这是一个最简单的继承。在Son类中并没有任何的自己的属性和方法,来看一下f12中的结构
也是不例外的使用了原型链来实现的继承,那么在es5中如果要实现这个继承应该怎么做?
使用babel把这段代码翻译成es5的语法,发现代码如下:
1 "use strict";
2
3 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; }; }();
4
5 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; }
6
7 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; }
8
9 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
10
11 /**
12 * Created by liuyc14 on 2016/6/28.
13 */
14
15 var Father = function () {
16 function Father(name, age) {
17 _classCallCheck(this, Father);
18
19 this.name = name;
20 this.age = age;
21 }
22
23 _createClass(Father, [{
24 key: "show",
25 value: function show() {
26 console.log("我叫:" + this.name + ", 今年" + this.age + "岁");
27 }
28 }]);
29
30 return Father;
31 }();
32
33 ;
34
35 var Son = function (_Father) {
36 _inherits(Son, _Father);
37
38 function Son() {
39 _classCallCheck(this, Son);
40
41 return _possibleConstructorReturn(this, Object.getPrototypeOf(Son).apply(this, arguments));
42 }
43
44 return Son;
45 }(Father);
46
47 ;
这些是babel编译完成后生成的es5语法的实现代码,看起来多了很多东西。
不着急,挑出几个重点来看一下(以后的例子都使用es5语法)
1. _createClass 方法,创建一个类,用到了defineProperties方法,就是给第一个参数的target对象,附加所有第二个参数的属性
2. _inherits 方法,实现继承的核心,用到了Object.create 和 Object.setPrototypeOf 方法
Object.create 方法:
这个方法接受两个参数,第一个参数为要继承的对象,第二参数为附加属性,返回一个创建后的对象。
举个例子:
1 function Father(name, age){
2 this.name = name;
3 this.age = age;
4 }
5
6 Father.prototype.show = function () {
7 console.log('我叫:' +this.name+', 今年'+this.age+'岁');
8 };
9
10 var obj = Object.create(Father.prototype);
11 console.log(obj.name); //return undefined
12 obj.show(); // return 我叫:undefined, 今年undefined岁
上面这个例子中,使用create方法,创建了一个obj对象,而且这个对象继承了Father.prototype对象的属性。(只有一个show方法,并没有 name 和 age 属性)
看到了这个作用以后,我们就可以使用create方法来实现es5的继承了
1 function Father(name, age){
2 this.name = name;
3 this.age = age;
4 }
5
6 Father.prototype.show = function () {
7 console.log('我叫:' +this.name+', 今年'+this.age+'岁');
8 };
9
10 function Son(name, age){
11 Father.call(this, name, age);
12 }
13 Son.prototype = Object.create(Father.prototype);
14 Son.prototype.constructor = Son;
15 Son.prototype.show = function () {
16 console.log('我是子类,我叫' + this.name + ', 今年' + this.age + '岁了');
17 };
18 var s = new Son('银角大王', 150); //return 我是子类,我叫银角大王, 今年150岁了
19 s.show();
上面的Son类在定义时,使用Father.call来继承Father的实例属性,使用Object.create方法来继承Father的原型,这样就完整的实现了继承,来看一下分析图
Son的实例s,在原型中有自己的show方法,再往上查找Father的原型,还可以看到show的原型,很清晰的层次结构
其实我们也可以不使用Object.create方法,使用Object.setPrototypeOf 方法来代替,达到同样的效果
把之前例子里第13行代码由
Son.prototype = Object.create(Father.prototype); =>
Object.setPrototypeOf(Son.prototype, Father.prototype);
这两行代码的效果是一样的,第二种方法更直观一些,就是把Son.prototype.__proto__ = Father.prototype 这样。
最后一个问题,我们如何才能向C#或者java里那样,在子类型中调用父类的方法呢?比如Son.prototype.show=function(){super.show()}这样
可以使用Object.getPrototypeOf(Son.prototype)方法来获取原型链的上一级,这样就可以获取到Father.prototype对象了,然后调用show()方法
1 Son.prototype.show = function () {
2 Object.getPrototypeOf(Son.prototype).show();
3 console.log('我是子类,我叫' + this.name + ', 今年' + this.age + '岁了');
4 };
但是调用Son的show方法,会log出: 我叫:undefined, 今年undefined岁; 我是子类,我叫银角大王, 今年150岁了
为什么会有undefined?看看刚才我们的f12结构图,Father.prototype中是没有name 和 age 属性的,那么怎么办?使用call方法啊!
下面贴出完整的类继承实现代码:
1 function Father(name, age){
2 this.name = name;
3 this.age = age;
4 }
5
6 Father.prototype.show = function () {
7 console.log('我叫:' +this.name+', 今年'+this.age+'岁');
8 };
9
10 function Son(name, age){
11 Father.call(this, name, age);
12 }
13 Object.setPrototypeOf(Son.prototype, Father.prototype);
14 Son.prototype.constructor = Son;
15 Son.prototype.$super = Object.getPrototypeOf(Son.prototype);//使用$super属性来指向父类的原型
16 Son.prototype.show = function () {
17 this.$super.show.call(this);
18 console.log('我是子类,我叫' + this.name + ', 今年' + this.age + '岁了');
19 };
20 var s = new Son('银角大王', 150);
21 s.show();
OK,今天的总结写完了,跟流水账一样,大家凑活看吧
posted on 2016-06-28 14:23 橙子瓣 阅读(1874) 评论(2) 编辑 收藏
评论: #1楼 2016-06-28 14:48 | BUG_Qusa
学习了。 支持(0) 反对(0) #2楼35869332016/12/22 11:19:49 2016-12-22 11:19 | mackxu
谢谢分享,学习了 支持(0)反对(0) http://pic.cnblogs.com/face/u351851.jpg?id=17165054 刷新评论刷新页面返回顶部 注册用户登录后才能发表评论,请 登录 或 注册, 访问网站首页。 【推荐】超50万VC++源码: 大型组态工控、电力仿真CAD与GIS源码库!
【前端】SpreadJS表格控件,可嵌入应用开发的在线Excel
【推荐】如何快速搭建人工智能应用?
· 爱奇艺、新英体育成立合资公司 入局在线体育平台
· 能让手机偷偷转账的“伪基站”,是个什么玩意儿
· 央行再开巨额罚单:国付宝4600万 支付宝412万
· 从腾讯离职引发天价赔偿案 竞业限制瞄准这类员工
· 谷歌与BlockApps合作 着手开发自家BaaS平台
» 更多新闻...
· 如何提高一个研发团队的“代码速度”?
· 成为一个有目标的学习者
· 历史转折中的“杭派工程师”
· 如何提高代码质量?
· 在腾讯的八年,我的职业思考
» 更多知识库文章...
前端码农,目前在北京
6年工作经验,4年.net & 2年前端
喜欢分享和学习
昵称:橙子瓣园龄:7年4个月
粉丝:21
关注: 7 +加关注
|
||||||
| 日 | 一 | 二 | 三 | 四 | 五 | 六 |
|---|---|---|---|---|---|---|
| 29 | 30 | 31 | 1 | 2 | 3 | 4 |
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 | 1 |
| 2 | 3 | 4 | 5 | 6 | 7 | 8 |
搜索
常用链接
我的标签
随笔档案
- 2016年9月 (1)
- 2016年7月 (1)
- 2016年6月 (1)
- 2015年11月 (1)
- 2015年6月 (2)
- 2015年5月 (6)
- 2015年4月 (2)
- 2015年2月 (1)
- 2015年1月 (2)
- 2014年12月 (1)
- 2014年9月 (6)
最新评论
- 1. Re:通过Redux源码学习基础概念一:简单例子入门
- 下一篇没有了吗?
- --要有好的心情
- 2. Re:es6继承 vs js原生继承(es5)
- 谢谢分享,学习了
- --mackxu
- 3. Re:跟着官网的例子学Reacjs (一)FilterableProductTable
- @Genius Zhang什么意思...
- --橙子瓣
- 4. Re:跟着官网的例子学Reacjs (一)FilterableProductTable
- 首先,博主的标题应该改一下
- --Genius Zhang
- 5. Re:nodejs学习篇 (1)webstorm创建nodejs + express + jade 的web 项目
- 想学习 nodejs 初学者,交流交流:)
- --加一
阅读排行榜
- 1. nodejs学习篇 (1)webstorm创建nodejs + express + jade 的web 项目(6510)
- 2. jQuery对Table一个字段排序(2917)
- 3. .net winform程序下使用firefox作为Web浏览器(2533)
- 4. es6继承 vs js原生继承(es5)(1873)
- 5. IOS学习笔记之 Socket 编程(900)
评论排行榜
- 1. jQuery对Table一个字段排序(6)
- 2. IOS学习笔记之 Socket 编程(6)
- 3. .net winform程序下使用firefox作为Web浏览器(3)
- 4. ios基础之UITableViewCell的重用(带示例原创)(2)
- 5. JPlayer使用之二,主要函数介绍(2)
推荐排行榜
- 1. es6继承 vs js原生继承(es5)(3)
- 2. jQuery.extend源码深层分析(2)
- 3. .net winform程序下使用firefox作为Web浏览器(1)
- 4. 通过Redux源码学习基础概念一:简单例子入门(1)
- 5. nodejs学习篇 (1)webstorm创建nodejs + express + jade 的web 项目(1)