最近在看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,今天的总结写完了,跟流水账一样,大家凑活看吧

转载于:https://www.cnblogs.com/chengzi/p/5623280.html

es6继承 vs js原生继承(es5)相关推荐

  1. 你真的理解JS的继承了吗?

    噫吁嚱,js之难,难于上青天 学习js的这几年,在原型链和继承上花了不知道多少时间,每当自以为已经吃透它的时候,总是不经意的会出现各种难以理解的幺蛾子.也许就像kyle大佬说的那样,js的继承真的是' ...

  2. oncreate为什么一定要调用父类的oncreat_为什么你老是讲不清楚JS的继承模式

    点击上方 "前端技术精选" 关注,星标或者置顶 17点30分准时推送,第一时间送达 作者:DBCdouble | 编辑:前端妹 来自:juejin.im/post/68696896 ...

  3. JS面试题--ES5和ES6有什么区别?

    ES5和ES6有什么区别? ES6新增了一些技术: 1.let声明变量和const声明常量,两个都有块级作用域ES5中是没有块级作用域的,并且var有变量提升,在let中,使用的变量一定要进行声明 2 ...

  4. 面试官问:JS的继承

    原文作者若川,掘金链接:https://juejin.im/post/5c433e216fb9a049c15f841b 写于2019年2月20日,现在发到公众号声明原创,之前被<前端大全> ...

  5. 学会这5种JS函数继承方式,前端面试你至少成功50%

    摘要:函数继承是在JS里比较基础也是比较重要的一部分,而且也是面试中常常要问到的.下面带你快速了解JS中有哪几种是经常出现且必须掌握的继承方式.掌握下面的内容面试也差不多没问题啦~ 本文分享自华为云社 ...

  6. js原型继承——prototype的使用

    文章目录 prototype的定义 原型链继承 修改prototype 继承的子类能否覆盖父类属性 总结 一些笔试题 第一题 第二题 小彩蛋 结语 参考文章 prototype的定义 javascri ...

  7. 【ES6】阮一峰ES6学习之Class的继承

    Class的继承 1. 概念 2. super关键字 3. 原生构造函数的继承 1. 概念 Class 通过extends关键字实现继承,让子类继承父类的属性和方法.extends 的写法比 ES5 ...

  8. 为什么你老是讲不清楚js的继承模式

    作者:DBCdouble https://juejin.im/post/6869689622676471816 一.前言 相信很多人在遇到面试中都遇到过被问到过JavaScript继承模式的问题,都能 ...

  9. JS实现继承的七种方法

    Class + extend Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多. class ColorPoint extends Point ...

最新文章

  1. 快速搞懂平面设计视觉思维的窍门
  2. pytorch处理多维输入的问题
  3. access的ole对象换成mysql_ACCESS的Ole对象读取写入
  4. mysql备份恢复出错,MySQL-记一次备份失败的排查过程
  5. python制作手机壁纸_Python爬取手机壁纸图片
  6. 龟兔赛跑预测(蓝桥杯)
  7. 初学者一些常用的SQL语句(一)
  8. html5pc转微信小程序,微信电脑版终于支持小程序 新版PC版微信实测
  9. 们--加强菲波那切数列
  10. 数据驱动编程之表驱动法
  11. QSS按钮样式设置的坑,按下(pressed)时按钮颜色不变化
  12. 认真学习设计模式之适配器模式(Adapter Pattern)/包装器模式
  13. Daraz平台怎么样?Daraz平台哪些产品热销?Daraz如何批量上传产品快速铺货?
  14. 【Github资源大汇总】 - 王朋
  15. [论文分享] Overcoming Catastrophic Forgetting in Incremental Few-Shot Learning by Finding Flat Minima
  16. 万兴剪刀手去水印教程_万兴神剪手怎么去水印教程_赶快收藏吧
  17. iOS WKWebView的使用以及遇到的问题
  18. 黑魂复刻游戏的碰撞摩擦问题——Unity随手记(2021.4.27)
  19. Datawhale-Pandas中文教程[9]
  20. 聊聊如何制作自定义ArcGIS Python工具箱

热门文章

  1. Selenium的一些技巧与错误处理
  2. OLTP和OLAP是什么
  3. [转] css3变形属性transform
  4. 使用 Gitolite 搭建 Git 服务器
  5. Windows下安装Redmine
  6. 《Business Rules Engine Overview》--《业务规则引擎概述》write by Mark Kamoski
  7. python替换缺失值,处理空值+生成图形+图形标准化
  8. java方法语法_Java基础语法----方法
  9. 今日恐慌与贪婪指数为93 贪婪程度有所缓解
  10. SAP License:搞砸SAP项目的3种方法