javascript 中的继承实例详解


Posted in Javascript onMay 05, 2017

javascript 中的继承实例详解

阅读目录

  • 原型链继承
  • 借用构造函数
  • 组合继承
  • 寄生组合式继承
  • 后记

继承有两种方式:接口继承和实现继承。接口继承只继承方法签名,而实现继承则继承实际的方法。

由于函数没有签名,在ECMAScript中无法实现接口继承。ECMAScript只支持实现继承,而且实现继承主要依靠原型链来实现。

下面介绍几种js的继承:

原型链继承

原型链继承实现的本质是重写原型对象,代之以一个新类型的实例。代码如下:

function SuperType() {
  this.property = true;
}

SuperType.prototype.getSuperValue = function() {
  return this.property;
};

function SubType() {
  this.subproperty = false;
}

// 继承了SuperType
SubType.prototype = new SuperType();

SubType.prototype.getSubValue = function () {
  return this.subproperty;
};

var instance = new SubType();

console.log(instance.getSuperValue()); // true

可以看到instance调用了父级的getSuperVlue()方法,实现了继承。

原型链的继承有如下问题:

  1. 包含引用类型值的原型时,在改变原型的引用类型时,会全部改了
  2. 在创建子类型的实例时,没有办法在不影响所有对象实例的情况下,给超类型的构造函数传递参数

示例代码如下:

function SuperType1() {
  this.colors = ['red', 'blue', 'green'];
}
function SubType1() {

}
SubType1.prototype = new SuperType1();
var instance1 = new SubType1();
instance1.colors.push('black');
console.log(instance1.colors); // [ 'red', 'blue', 'green', 'black' ]

var instance2 = new SubType1();
console.log(instance2.colors); // [ 'red', 'blue', 'green', 'black' ]

可以发现,instance1和instance2的colors属性是共享的,这就出问题了,同时也能够看出,在new一个新的方法时,如果传值的话,是传不到父级的。

借用构造函数

原理是在子类型构造函数的内部调用超类型构造函数,因为函数只不过是在特定环境中执行代码的对象,这样就可以获取父级的方法和属性了。

代码如下:

function SuperType(name) {
  this.name = name;
}

function SubType(name) {
  // 继承了SuperType,同时还传递了参数
  SuperType.call(this, name);

  // 实例属性
  this.age = 29;
}

var instance = new SubType('Bob');

console.log(instance.name); // Bob
console.log(instance.age); // 29

可以看出,调用构造函数继承解决了向父类型传参的问题,但调用构造函数也有其自身的问题:

  1. 方法都在构造函数中,函数复用没有了。
  2. 超类型的原型中定义的方法,对子类型而言是不可见的。

第一个问题很明显,针对第二个问题的解释是,由于只是执行了一次函数,并没有new出新对象,故而父类prototype中的方法对子类是不可见的。

组合继承

由于原型链继承和借用构造函数继承都有缺陷,故而在实际中一般不会单独使用。

组合继承是借用其两者的优点而产生的继承方法。

其原理是使用原型链实现对原型属性和方法的继承,通过借用构造函数来实现对实例属性的继承。

代码如下:

function SuperType(name) {
  this.name = name;
  this.colors = ['red', 'blue', 'green'];
}

SuperType.prototype.sayName = function() {
  console.log(this.name);
};

function SubType(name, age) {
  // 继承属性
  SuperType.call(this, name);

  this.age = age;
}
// 继承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function() {
  console.log(this.age);
};

var instance1 = new SubType('Nicholas', 29);
instance1.colors.push('black');

console.log(instance1.colors); // [ 'red', 'blue', 'green', 'black' ]
instance1.sayName(); // Nicholas
instance1.sayAge(); // 29

var instance2 = new SubType('Greg', 27);

console.log(instance2.colors); // [ 'red', 'blue', 'green' ]
instance2.sayName(); // Greg
instance2.sayAge(); // 27

组合继承能够解决上面两种继承方式带来的问题,但是组合继承也有其自身的小问题,那就是会调用两次超类型构造函数,通过分析便可知道 一次是在创建子类型原型的时候,另一次是在子类型构造函数内部。

寄生组合式继承

寄生组合式继承的原理为通过借用构造函数来继承属性,通过原型链的混成形式来继承方法,基本思路是不必为了指定子类型的原型而调用超类型的构造函数,我们所需要的无非就是超类型原型的一个副本而已。

代码如下:

function object(o) {
  function F() {}
  F.prototype = o;
  return new F;
}

function inheritPrototype(subType, superType) {
  var prototype = object(superType.prototype);
  prototype.constructor = subType;
  subType.prototype = prototype;
}

function SuperType(name) {
  this.name = name;
  this.colors = ['red', 'blue', 'green'];
}

SuperType.prototype.sayName = function() {
 console.log(this.name);
};

function SubType(name, age) {
  SuperType.call(this, name);

  this.age = age;
}

// 继承的关键
inheritPrototype(SubType, SuperType);

SubType.prototype.sayAge = function() {
  console.log(this.age);
};

var instance = new SubType('天涯', 23);
instance.sayName();
instance.sayAge();

寄生组合式继承只有在调用构造函数时执行了一遍超类型,解决了组合继承的小问题。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

Javascript 相关文章推荐
匹配任意字符的正则表达式写法
Apr 29 Javascript
fancybox1.3.1 基于Jquery的插件在IE中图片显示问题
Oct 01 Javascript
jquery ajax跨域解决方法(json方式)
Feb 04 Javascript
JQuery选中checkbox方法代码实例(全选、反选、全不选)
Apr 27 Javascript
Jquery元素追加和删除的实现方法
May 24 Javascript
jQuery实用小技巧_输入框文字获取和失去焦点的简单实例
Aug 25 Javascript
jQuery实现的放大镜效果示例
Sep 13 Javascript
js 获取本地文件及目录的方法(推荐)
Nov 10 Javascript
微信小程序--特定区域滚动到顶部时固定的方法
Apr 28 Javascript
JavaScrip数组去重操作实例小结
Jun 20 Javascript
JS函数进阶之prototy用法实例分析
Jan 15 Javascript
Angular之jwt令牌身份验证的实现
Feb 14 Javascript
JavaScript函数表达式详解及实例
May 05 #Javascript
Node.js中的http请求客户端示例(request client)
May 04 #Javascript
Bootstrap布局之栅格系统学习笔记
May 04 #Javascript
vue.js开发环境搭建教程
May 04 #Javascript
jQuery使用JSONP实现跨域获取数据的三种方法详解
May 04 #jQuery
详解webpack es6 to es5支持配置
May 04 #Javascript
angular 基于ng-messages的表单验证实例
May 04 #Javascript
You might like
thinkphp隐藏index.php/home并允许访问其他模块的实现方法
2016/10/13 PHP
php多进程并发编程防止出现僵尸进程的方法分析
2020/02/28 PHP
Prototype源码浅析 String部分(四)之补充
2012/01/16 Javascript
qTip2 精致的基于jQuery提示信息插件
2012/02/17 Javascript
高性能Javascript笔记 数据的存储与访问性能优化
2012/08/02 Javascript
让页面上两个div中的滚动条(滑块)同步运动示例
2013/08/07 Javascript
JavaScript与jQuery实现的闪烁输入效果
2016/02/18 Javascript
详解Angular的数据显示优化处理
2016/12/26 Javascript
Vue声明式渲染详解
2017/05/17 Javascript
利用vue.js把静态json绑定bootstrap的table方法
2018/08/28 Javascript
vue+echarts实现动态绘制图表及异步加载数据的方法
2018/10/17 Javascript
vue2.0 如何在hash模式下实现微信分享
2019/01/22 Javascript
微信小程序表单验证插件WxValidate的二次封装功能(终极版)
2019/09/03 Javascript
在layui.use 中自定义 function 的正确方法
2019/09/16 Javascript
vue 使用vant插件做tabs切换和无限加载功能的实现
2020/11/04 Javascript
JavaScript Html实现移动端红包雨功能页面
2021/01/10 Javascript
python爬虫入门教程之点点美女图片爬虫代码分享
2014/09/02 Python
python selenium 获取标签的属性值、内容、状态方法
2018/06/22 Python
python学生信息管理系统(初级版)
2018/10/17 Python
python 遍历pd.Series的index和value
2019/11/26 Python
python dataframe NaN处理方式
2019/12/26 Python
Python使用进程Process模块管理资源
2020/03/05 Python
Django调用百度AI接口实现人脸注册登录代码实例
2020/04/23 Python
pycharm 激活码及使用方式的详细教程
2020/05/12 Python
Python 如何实现访问者模式
2020/07/28 Python
python爬虫要用到的库总结
2020/07/28 Python
python如何实现DES加密
2020/09/21 Python
css3 旋转按钮 使用CSS3创建一个旋转可变色按钮
2012/12/31 HTML / CSS
花园仓库建筑:Garden Buildings Direct
2018/02/16 全球购物
施华洛世奇韩国官网:SWAROVSKI韩国
2018/06/05 全球购物
产品委托授权书范本
2014/09/16 职场文书
2015年生活老师工作总结
2015/05/27 职场文书
学术会议开幕词
2016/03/03 职场文书
市语委办2016年第十九届“推普周”活动总结
2016/04/05 职场文书
Python利器openpyxl之操作excel表格
2021/04/17 Python
pandas:get_dummies()与pd.factorize()的用法及区别说明
2021/05/21 Python