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 相关文章推荐
走出JavaScript初学困境—js初学
Dec 29 Javascript
window.js 主要包含了页面的一些操作
Dec 23 Javascript
最流行的Node.js精简型和全栈型开发框架介绍
Feb 26 Javascript
有关easyui-layout中的收缩层无法显示标题的解决办法
May 10 Javascript
js编写的treeview使用方法
Nov 11 Javascript
js 动态生成html 触发事件传参字符转义的实例
Feb 14 Javascript
从零学习node.js之搭建http服务器(二)
Feb 21 Javascript
网页中的图片查看器viewjs使用方法
Jul 11 Javascript
AngularJS中的作用域实例分析
May 16 Javascript
vue项目打包后怎样优雅的解决跨域
May 26 Javascript
javascript设计模式 ? 备忘录模式原理与用法实例分析
Apr 21 Javascript
react组件基本用法示例小结
Apr 27 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
Win9x/ME下Apache+PHP安装配置
2006/10/09 PHP
PHP新手上路(十一)
2006/10/09 PHP
PHP+Mysql+jQuery中国地图区域数据统计实例讲解
2015/10/10 PHP
PHP实现用session来实现记录用户登陆信息
2018/10/15 PHP
thinkphp 5框架实现登陆,登出及session登陆状态检测功能示例
2019/10/10 PHP
javascript json2 使用方法
2010/03/16 Javascript
基于Jquery的文字滚动跑马灯插件(一个页面多个滚动区)
2010/07/26 Javascript
jquery each的几种常用的使用方法示例
2014/01/21 Javascript
浅谈jQuery中的事件
2015/03/23 Javascript
jQuery插件datepicker 日期连续选择
2015/06/12 Javascript
JS实现仿腾讯微博无刷新删除微博效果代码
2015/10/16 Javascript
angularjs实现文字上下无缝滚动特效代码
2016/09/04 Javascript
浅谈jquery拼接字符串效率比较高的方法
2017/02/22 Javascript
win系统下nodejs环境安装配置
2017/05/04 NodeJs
node.js中EJS 模板快速入门教程
2017/05/08 Javascript
js构造函数创建对象是否加new问题
2018/01/22 Javascript
用vue2.0实现点击选中active其他选项互斥的效果
2018/04/12 Javascript
Javascript读写cookie的实例源码
2019/03/16 Javascript
JS实现电商商品展示放大镜特效
2020/01/07 Javascript
详解Python字符串对象的实现
2015/12/24 Python
Python3.4实现从HTTP代理网站批量获取代理并筛选的方法示例
2017/09/26 Python
python 高效去重复 支持GB级别大文件的示例代码
2018/11/08 Python
python实现一组典型数据格式转换
2018/12/15 Python
详解Python3除法之真除法、截断除法和下取整对比
2019/05/23 Python
pandas 如何分割字符的实现方法
2019/07/29 Python
使用pandas读取文件的实现
2019/07/31 Python
Django单元测试工具test client使用详解
2019/08/02 Python
python super的使用方法及实例详解
2019/09/25 Python
wxpython+pymysql实现用户登陆功能
2019/11/19 Python
Gina Bacconi官网:吉娜贝康尼连衣裙和礼服
2018/04/24 全球购物
护理专业推荐信
2013/11/07 职场文书
服装设计专业毕业生求职信
2014/04/09 职场文书
普通话演讲稿
2014/09/03 职场文书
教你怎么用PyCharm为同一服务器配置多个python解释器
2021/05/31 Python
python中的getter与setter你了解吗
2022/03/24 Python
Python OpenCV实现图像模板匹配详解
2022/04/07 Python