JavaScript类的继承操作实例总结


Posted in Javascript onDecember 20, 2018

本文实例总结了JavaScript类的继承操作。分享给大家供大家参考,具体如下:

一、类式继承

首先要做的是创建构造函数。按惯例,其名称就是类名,首字母应该大写。在构造函数中,创建实例属性要用关键字this 。类的方法则被添加到prototype对象中。要创建该类的实例,只需结合关键字new调用这构造函数即可。

/* Class Person. */
function Person(name) {
 this.name = name;
}
Person.prototype.getName = function() {
 return this.name;
}
var reader = new Person('John Smith');
reader.getName();

二、原型链

JavaScript的每个对象都有一个名为prototype的属性,这个属性要么指向另一个对象,要么是null.在访问对象的某个成员时,如果这个成员未见于当前对象,那么就会到prototype所指的对象中去查找。如果还是没有找到,那么就会沿着原型链逐一访问每个原型对象,直到找到这个成员。这意味着让一个类继承另一个类,只需将子类的prototype设置为超类的一个实例即可。

为了让Author继承Person,必须手工将Author的prototype设置为Person的一个实例。最后一步是将prototypeconstruct属性重设为Author(因为prototype属性设置为Person的实例)时,其construct属性被抹除了。

function Author(name, books) {
 Person.call(this, name); // Call the superclass' constructor in the scope of this.
 this.books = books; // Add an attribute to Author.
}
Author.prototype = new Person(); // Set up the prototype chain.
Author.prototype.constructor = Author; // Set the constructor attribute to Author.
Author.prototype.getBooks = function() { // Add a method to Author.
 return this.books;
};
var author = [];
author[0] = new Author('Dustin Diaz', ['JavaScript Design Patterns']);
author[1] = new Author('Ross Harmes', ['JavaScript Design Patterns']);
console.log(author[1].getName());
console.log(author[1].getBooks());

三、extend函数

为了简化类的声明,可以把派生子类的整个过程包装在一个名为extend的函数中。它的作用与其他语言的extend关键字类似,即基于一个给定的类的结构创建一个新的类:

function extend(subClass, superClass) {
 var F = function() {};
 F.prototype = superClass.prototype;
 subClass.prototype = new F();
 subClass.prototype.constructor = subClass;
}

其实所做的事与之前的是一样的。它先设置了prototype,然后再将其constructor重设为恰当的值。并且中间利用了一个空函数,这样就可以避免创建超类的实例。使用extend继承的写法:

function Person(name) {
 this.name = name;
}
Person.prototype.getName = function() {
 return this.name;
}
/* Class Author. */
function Author(name, books) {
 Person.call(this, name);
 this.books = books;
}
extend(Author, Person);
Author.prototype.getBooks = function() {
 return this.books;
};

但上面的存在一个问题就是超类Person的名称被固化在Author类的声明当中。更普世性的做法应该像下面这样:

/* Extend function, improved. */
function extend(subClass, superClass) {
 var F = function() {};
 F.prototype = superClass.prototype;
 subClass.prototype = new F();
 subClass.prototype.constructor = subClass;
 subClass.superclass = superClass.prototype;
 if(superClass.prototype.constructor == Object.prototype.constructor) {
  superClass.prototype.constructor = superClass;
 }
}
/* Class Author. */
function Author(name, books) {
 Author.superclass.constructor.call(this, name);
 this.books = books;
}
extend(Author, Person);
Author.prototype.getBooks = function() {
 return this.books;
};
Author.prototype.getName = function() {
 var name = Author.superclass.getName.call(this);
 return name + ', Author of ' + this.getBooks().join(', ');
};

这个extend改进之后,多了一个superclass的属性,这个属性可以弱化Author和Person之间的耦合。extend后面三行用来确保超类的construtor已经被正确设置了。有了superclass的属性,就可以直接调用超类中的方法。这在既要重新定义超类的某个方法而又想访问其在超类中的实现时可以派上用场。例如,为了用一个新的getName的方法重新定义Person类中的同名方法,你可以先用Author.superclass.getName获得作者的名字,然后再次基础上添加新的信息。

四、原型继承

原型式继承与类式继承截然不同,我们在学习他的时候,最好忘记自己关于类和实例的一切知识,只从对象的角度来思考。使用原型式继承时,并不需要用类来定义对象的结构,只需直接创建一个对像就可以。这个对象随后可以被新的对象使用,该对象被称为原型对象。

下面使用原型对象来重新设计上面Person和Author:

var Person = {
 name: 'default name',
 getName: function() {
  return this.name;
 }
};
var reader = clone(Person);
alert(reader.getName()); // This will output 'default name'.
reader.name = 'John Smith';
alert(reader.getName()); // This will now output 'John Smith'.

clone函数可以用来创建新的类Person对象,创建一个空对象,并且该对象的原型对象被设置为person。当新对象中找不到某个方法时就会在原型对象中查找。

你不必去为了创建Author而定义一个Person子类,只要执行一次克隆就可以:

var Author = clone(Person);
Author.books = []; // Default value.
Author.getBooks = function() {
 return this.books;
}

然后你可以重定义该克隆中的方法和属性。可以修改Person的默认值。也可以添加新的属性和方法。这样一来就创建了一个新的原型对象,你可以将其用于创建新的Author对象:

var author = [];
author[0] = clone(Author);
author[0].name = 'Dustin Diaz';
author[0].books = ['JavaScript Design Patterns'];
author[1] = clone(Author);
author[1].name = 'Ross Harmes';
author[1].books = ['JavaScript Design Patterns'];
author[1].getName();
author[1].getBooks();

clone函数的写法:

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

五、原型继承和类式继承之间的比较

可以自己去总结、
从内存,适用范围,优缺点等方面去分析

六、掺元类

有一种重用代码的方法不需要用到严格的继承,如果想把一个函数运用到多个类当中,可以通过扩充的方法让这些类共享函数。其实际大体做法就是:先创建一个包含各种通用的方法类,然后再扩充其他类,这种包含通用方法类称为掺元类,他们通常不会被实例化和直接调用,其存在的目的是向其他类提供自己的方法。

var Mixin = function() {};
Mixin.prototype = {
 serialize: function() {
  var output = [];
  for(key in this) {
   output.push(key + ': ' + this[key]);
  }
  return output.join(', ');
 }
};
augment(Author, Mixin);
var author = new Author('Ross Harmes', ['JavaScript Design Patterns']);
var serializedString = author.serialize();
function augment(receivingClass, givingClass) {
 for(methodName in givingClass.prototype) {
  if(!receivingClass.prototype[methodName]) {
   receivingClass.prototype[methodName] = givingClass.prototype[methodName];
  }
 }
}

但是有时候你并不需要所有的方法,因此我们还需要提供额外的参数来选择我们所需要的方法。如果不提供,那就全部复制。

function augment(receivingClass, givingClass) {
 if(arguments[2]) { // Only give certain methods.
  for(var i = 2, len = arguments.length; i < len; i++) {
   receivingClass.prototype[arguments[i]] = givingClass.prototype[arguments[i]];
  }
 }
 else { // Give all methods.
  for(methodName in givingClass.prototype) {
   if(!receivingClass.prototype[methodName]) {
    receivingClass.prototype[methodName] = givingClass.prototype[methodName];
   }
  }
 }
}

更多关于JavaScript相关内容还可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
js中将String转换为number以便比较
Jul 08 Javascript
Angular用来控制元素的展示与否的原生指令介绍
Jan 07 Javascript
jQuery选择器源码解读(一):Sizzle方法
Mar 31 Javascript
简介JavaScript中Math.LOG10E属性的使用
Jun 14 Javascript
JS实现图片平面旋转的方法
Mar 01 Javascript
jQuery validate插件功能与用法详解
Dec 15 Javascript
利用jQuery实现一个简单的表格上下翻页效果
Mar 14 Javascript
js推箱子小游戏步骤代码解析
Jan 10 Javascript
Vue+axios实现统一接口管理的方法
Jul 23 Javascript
Vue 实时监听窗口变化 windowresize的两种方法
Nov 06 Javascript
开发Node CLI构建微信小程序脚手架的示例
Mar 27 Javascript
javascript 模块依赖管理的本质深入详解
Apr 30 Javascript
vue返回上一页面时回到原先滚动的位置的方法
Dec 20 #Javascript
详解Vue.js自定义tipOnce指令用法实例
Dec 19 #Javascript
JavaScript创建对象方式总结【工厂模式、构造函数模式、原型模式等】
Dec 19 #Javascript
JavaScript链式调用实例浅析
Dec 19 #Javascript
浅谈vue后台管理系统权限控制思考与实践
Dec 19 #Javascript
如何为vue的项目添加单元测试
Dec 19 #Javascript
浅谈Angular7 项目开发总结
Dec 19 #Javascript
You might like
php数组函数序列之in_array() - 查找数组中是否存在指定值
2011/11/07 PHP
PHP的变量类型和作用域详解
2014/03/12 PHP
PHP中可以自动分割查询字符的Parse_str函数使用示例
2014/07/25 PHP
PHP命名空间和自动加载类
2016/04/03 PHP
搭建自己的PHP MVC框架详解
2017/08/16 PHP
JS面向对象、prototype、call()、apply()
2009/05/14 Javascript
jQuery开发者都需要知道的5个小技巧
2010/01/08 Javascript
JQuery实现简单时尚快捷的气泡提示插件
2012/12/20 Javascript
jquery.messager.js插件导致页面抖动的解决方法
2013/07/14 Javascript
有效提高JavaScript执行效率的几点知识
2015/01/31 Javascript
jQuery实现仿腾讯视频列表分页效果的方法
2015/08/07 Javascript
jQuery头像裁剪工具jcrop用法实例(附演示与demo源码下载)
2016/01/22 Javascript
jQuery实现下拉框多选 jquery-multiselect 的实例代码
2016/07/14 Javascript
vue轮播图插件vue-awesome-swiper的使用代码实例
2017/07/10 Javascript
node文字生成图片的示例代码
2017/10/26 Javascript
解决mui框架中switch开关通过js控制开或者关状态时小圆点不动的问题
2019/09/03 Javascript
微信小程序自定义tabBar的踩坑实践记录
2020/11/06 Javascript
python多线程抓取天涯帖子内容示例
2014/04/03 Python
Python第三方库的安装方法总结
2016/06/06 Python
Python一键安装全部依赖包的方法
2019/08/12 Python
使用pandas实现连续数据的离散化处理方式(分箱操作)
2019/11/22 Python
OpenCV 表盘指针自动读数的示例代码
2020/04/10 Python
CSS3的RGBA中关于整数和百分比值的转换
2015/08/04 HTML / CSS
英国婴儿和儿童服装网站:Vertbaudet
2018/04/02 全球购物
STAY JAPAN台湾:预订日本民宿
2018/07/22 全球购物
经济实惠的豪华背包和行李袋:Packs Project
2018/10/17 全球购物
英文版区域经理求职信
2013/10/23 职场文书
服装机修工岗位职责
2013/12/26 职场文书
旅游管理专业生自荐信范文
2014/01/02 职场文书
初中生物教学反思
2014/01/10 职场文书
2014年教师党员自我评价范文
2014/09/22 职场文书
《赵州桥》教学反思
2016/02/17 职场文书
如何写一份成功的商业计划书
2019/06/25 职场文书
jquery插件实现代码雨特效
2021/04/24 jQuery
详解Nginx 被动检查服务器的存活状态
2021/10/16 Servers
VUE之图片Base64编码使用ElementUI组件上传
2022/04/09 Vue.js