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,今天的总结写完了,跟流水账一样,大家凑活看吧
转载于:https://www.cnblogs.com/chengzi/p/5623280.html
es6继承 vs js原生继承(es5)相关推荐
- 你真的理解JS的继承了吗?
噫吁嚱,js之难,难于上青天 学习js的这几年,在原型链和继承上花了不知道多少时间,每当自以为已经吃透它的时候,总是不经意的会出现各种难以理解的幺蛾子.也许就像kyle大佬说的那样,js的继承真的是' ...
- oncreate为什么一定要调用父类的oncreat_为什么你老是讲不清楚JS的继承模式
点击上方 "前端技术精选" 关注,星标或者置顶 17点30分准时推送,第一时间送达 作者:DBCdouble | 编辑:前端妹 来自:juejin.im/post/68696896 ...
- JS面试题--ES5和ES6有什么区别?
ES5和ES6有什么区别? ES6新增了一些技术: 1.let声明变量和const声明常量,两个都有块级作用域ES5中是没有块级作用域的,并且var有变量提升,在let中,使用的变量一定要进行声明 2 ...
- 面试官问:JS的继承
原文作者若川,掘金链接:https://juejin.im/post/5c433e216fb9a049c15f841b 写于2019年2月20日,现在发到公众号声明原创,之前被<前端大全> ...
- 学会这5种JS函数继承方式,前端面试你至少成功50%
摘要:函数继承是在JS里比较基础也是比较重要的一部分,而且也是面试中常常要问到的.下面带你快速了解JS中有哪几种是经常出现且必须掌握的继承方式.掌握下面的内容面试也差不多没问题啦~ 本文分享自华为云社 ...
- js原型继承——prototype的使用
文章目录 prototype的定义 原型链继承 修改prototype 继承的子类能否覆盖父类属性 总结 一些笔试题 第一题 第二题 小彩蛋 结语 参考文章 prototype的定义 javascri ...
- 【ES6】阮一峰ES6学习之Class的继承
Class的继承 1. 概念 2. super关键字 3. 原生构造函数的继承 1. 概念 Class 通过extends关键字实现继承,让子类继承父类的属性和方法.extends 的写法比 ES5 ...
- 为什么你老是讲不清楚js的继承模式
作者:DBCdouble https://juejin.im/post/6869689622676471816 一.前言 相信很多人在遇到面试中都遇到过被问到过JavaScript继承模式的问题,都能 ...
- JS实现继承的七种方法
Class + extend Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多. class ColorPoint extends Point ...
最新文章
- 快速搞懂平面设计视觉思维的窍门
- pytorch处理多维输入的问题
- access的ole对象换成mysql_ACCESS的Ole对象读取写入
- mysql备份恢复出错,MySQL-记一次备份失败的排查过程
- python制作手机壁纸_Python爬取手机壁纸图片
- 龟兔赛跑预测(蓝桥杯)
- 初学者一些常用的SQL语句(一)
- html5pc转微信小程序,微信电脑版终于支持小程序 新版PC版微信实测
- 们--加强菲波那切数列
- 数据驱动编程之表驱动法
- QSS按钮样式设置的坑,按下(pressed)时按钮颜色不变化
- 认真学习设计模式之适配器模式(Adapter Pattern)/包装器模式
- Daraz平台怎么样?Daraz平台哪些产品热销?Daraz如何批量上传产品快速铺货?
- 【Github资源大汇总】 - 王朋
- [论文分享] Overcoming Catastrophic Forgetting in Incremental Few-Shot Learning by Finding Flat Minima
- 万兴剪刀手去水印教程_万兴神剪手怎么去水印教程_赶快收藏吧
- iOS WKWebView的使用以及遇到的问题
- 黑魂复刻游戏的碰撞摩擦问题——Unity随手记(2021.4.27)
- Datawhale-Pandas中文教程[9]
- 聊聊如何制作自定义ArcGIS Python工具箱