最近在看es2015的一些语法,最实用的应该就是继承这个新特性了。比如下面的代码:

 $(function(){
class Father{
constructor(name, age){
this.name = name;
this.age = age;
} show(){
console.log(`我叫:${this.name}, 今年${this.age}岁`);
}
};
class Son extends Father{}; let son = new Son('金角大王', 200);
son.show();//return 我叫:金角大王, 今年200岁 });

这是一个最简单的继承。在Son类中并没有任何的自己的属性和方法,来看一下f12中的结构

也是不例外的使用了原型链来实现的继承,那么在es5中如果要实现这个继承应该怎么做?

使用babel把这段代码翻译成es5的语法,发现代码如下:

 "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"); } }

 /**
* Created by liuyc14 on 2016/6/28.
*/ var Father = function () {
function Father(name, age) {
_classCallCheck(this, Father); this.name = name;
this.age = age;
} _createClass(Father, [{
key: "show",
value: function show() {
console.log("我叫:" + this.name + ", 今年" + this.age + "岁");
}
}]); return Father;
}(); ; var Son = function (_Father) {
_inherits(Son, _Father); function Son() {
_classCallCheck(this, Son); return _possibleConstructorReturn(this, Object.getPrototypeOf(Son).apply(this, arguments));
} return Son;
}(Father); ;

这些是babel编译完成后生成的es5语法的实现代码,看起来多了很多东西。

不着急,挑出几个重点来看一下(以后的例子都使用es5语法

1. _createClass 方法,创建一个类,用到了defineProperties方法,就是给第一个参数的target对象,附加所有第二个参数的属性

2. _inherits 方法,实现继承的核心,用到了Object.create 和 Object.setPrototypeOf 方法

Object.create 方法:

这个方法接受两个参数,第一个参数为要继承的对象,第二参数为附加属性,返回一个创建后的对象。

举个例子:

 function Father(name, age){
this.name = name;
this.age = age;
} Father.prototype.show = function () {
console.log('我叫:' +this.name+', 今年'+this.age+'岁');
}; var obj = Object.create(Father.prototype);
console.log(obj.name); //return undefined
obj.show(); // return 我叫:undefined, 今年undefined岁

上面这个例子中,使用create方法,创建了一个obj对象,而且这个对象继承了Father.prototype对象的属性。(只有一个show方法,并没有 name 和 age 属性)

看到了这个作用以后,我们就可以使用create方法来实现es5的继承了

 function Father(name, age){
this.name = name;
this.age = age;
} Father.prototype.show = function () {
console.log('我叫:' +this.name+', 今年'+this.age+'岁');
}; function Son(name, age){
Father.call(this, name, age);
}
Son.prototype = Object.create(Father.prototype);
Son.prototype.constructor = Son;
Son.prototype.show = function () {
console.log('我是子类,我叫' + this.name + ', 今年' + this.age + '岁了');
};
var s = new Son('银角大王', 150); //return 我是子类,我叫银角大王, 今年150岁了
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()方法

 Son.prototype.show = function () {
Object.getPrototypeOf(Son.prototype).show();
console.log('我是子类,我叫' + this.name + ', 今年' + this.age + '岁了');
};

但是调用Son的show方法,会log出: 我叫:undefined, 今年undefined岁; 我是子类,我叫银角大王, 今年150岁了

为什么会有undefined?看看刚才我们的f12结构图,Father.prototype中是没有name 和 age 属性的,那么怎么办?使用call方法啊!

下面贴出完整的类继承实现代码:

 function Father(name, age){
this.name = name;
this.age = age;
} Father.prototype.show = function () {
console.log('我叫:' +this.name+', 今年'+this.age+'岁');
}; function Son(name, age){
Father.call(this, name, age);
}
Object.setPrototypeOf(Son.prototype, Father.prototype);
Son.prototype.constructor = Son;
Son.prototype.$super = Object.getPrototypeOf(Son.prototype);//使用$super属性来指向父类的原型
Son.prototype.show = function () {
this.$super.show.call(this);
console.log('我是子类,我叫' + this.name + ', 今年' + this.age + '岁了');
};
var s = new Son('银角大王', 150);
s.show();

OK,今天的总结写完了,跟流水账一样,大家凑活看吧

es6继承 vs js原生继承(es5)的更多相关文章

  1. js原生继承几种方式

    js原生继承 js本身并没有继承和类的概念,本质上是通过原型链(prototype)的形式实现的. 1.先写两个构造函数Parent和Child,用于将Child继承Parent function P ...

  2. ES6之前,JS的继承

    继承的概念 谈到继承,就不得不谈到类和对象的概念. 类是抽象的,它是拥有共同的属性和行为的抽象实体. 对象是具体的,它除了拥有类共同的属性和行为之外,可能还会有一些独特的属性和行为. 打个比方: 人类 ...

  3. js原生继承之——原型式继承实例

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8&qu ...

  4. js原生继承之——组合式继承实例

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8&qu ...

  5. js原生继承之——构造函数式继承实例

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8&qu ...

  6. js原生继承之——类式继承实例(推荐使用)

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8&qu ...

  7. JS 实现继承的方法 ES6 and ES5

    继承 ES6 方法  (类的继承) ES6中有一个属性的 extends 语法: ​ • class Father {} ​ • class Son extends Father{} ​ 注意:是子类 ...

  8. JS类继承常用方式发展史

    JS类继承常用方式发展史 涉及知识点 构造函数方式继承 1-继承单个对象 1.1 多步走初始版 1.2 多步走优化版 1.3 Object.create()方式 2-继承多个对象 2.1 遍历 Obj ...

  9. ES6内建对象的继承

    在ES6之前, JS是无法通过继承的方式创建属于自己的特殊数组的, 也就是说可以使用原型链来继承数组的一些方法, 但是某些返回一个数组的方法返回的值还是一个Array的实例, 例如slice, len ...

随机推荐

  1. 【源码分享】WPF漂亮界面框架实现原理分析及源码分享

    1 源码下载 2 OSGi.NET插件应用架构概述 3 漂亮界面框架原理概述 4 漂亮界面框架实现  4.1 主程序  4.2 主程序与插件的通讯   4.2.1 主程序获取插件注册的服务   4.2 ...

  2. DWZ错误的解决:0x800a13af - Microsoft JScript 运行时错误: 重新声明常量“document”

    在写完Login后,需要跳转到Index中,就是DWZ的主界面,结果出现如下问题: 0x800a13af - Microsoft JScript 运行时错误: 重新声明常量“document” 费了很 ...

  3. Java虚拟机13:互斥同步、锁优化及synchronized和volatile

    互斥同步 互斥同步(Mutual Exclusion & Synchronization)是常见的一种并发正确性保证手段.同步是指子啊多个线程并发访问共享数据时,保证共享数据在同一时刻只能被一 ...

  4. AMD加载器实现笔记(三)

    上一篇文章中我们为config添加了baseUrl和packages的支持,那么这篇文章中将会看到对shim与paths的支持. 要添加shim与paths,第一要务当然是了解他们的语义与用法.先来看 ...

  5. Json序列化之.NET开源类库Newtonsoft.Json的研究

     一.Json简介 JSON(全称为JavaScript Object Notation) 是一种轻量级的数据交换格式.它是基于JavaScript语法标准的一个子集. JSON采用完全独立于语言的文 ...

  6. COM思想的背后

    最近看公司的一些新产品和框架 , 发现清一色的“COM思想架构 ”, 这里说的“COM思想架构”是指不完全是标准COM组件的方式,而是指在设计上用到了COM思想. COM组件技术大概在1993年产生, ...

  7. C/C++中动态链接库的创建和调用

    DLL 有助于共享数据和资源.多个应用程序可同时访问内存中单个DLL 副本的内容.DLL 是一个包含可由多个程序同时使用的代码和数据的库.下面为你介绍C/C++中动态链接库的创建和调用. 动态连接库的 ...

  8. 深入CSS,让网页开发少点“坑”

    通常我们在学习CSS的时候,感觉语法很容易掌握,实际应用中却碰到各式各样难以填补的“坑”,为避免大家受到同样的困惑与不解,本文详细讲解了CSS中优先级和Stacking Context等高级特性.让你 ...

  9. easy-ui 小白进阶史(一):加载数据,easy-ui显示

    作为一个没上过大学,没经过正规培训的96年的小白来说,找工作就没报特别大的希望,大不了找不到在回炉重造,继续学... 终于在海投了200份的简历之后...终于找到了...面试也挺简单的,,,第二天就去 ...

  10. java source not found

    今天的挑战是,为什么与源码明明放在本机,调试的时候却说source not found呢? 这个是因为,我重新建立了debug,然后没有选择对应的项目. 另外一个问题是,如果给底层的jar附上源码呢?