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 相关文章推荐
JQuery团队打造的javascript单元测试工具QUnit介绍
Feb 26 Javascript
使用JavaScript和C#中获得referer
Nov 14 Javascript
jQuery实现仿新浪微博浮动的消息提示框(可智能定位)
Oct 10 Javascript
浅谈js的url解析函数封装
Jun 28 Javascript
JS中Array数组学习总结
Jan 18 Javascript
总结js中的一些兼容性易错的问题
Dec 18 Javascript
Vue实现美团app的影院推荐选座功能【推荐】
Aug 29 Javascript
react在安卓中输入框被手机键盘遮挡问题的解决方法
Sep 03 Javascript
JS重学系列之聊聊new操作符
Mar 04 Javascript
简述pm2常用命令集合及配置文件说明
May 30 Javascript
vue项目使用.env文件配置全局环境变量的方法
Oct 24 Javascript
JS实现压缩上传图片base64长度功能
Dec 03 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的ob_start() 控制您的浏览器cache
2009/08/03 PHP
Yii快速入门经典教程
2015/12/28 PHP
深入理解PHP之OpCode原理详解
2016/06/01 PHP
Yii2框架数据库简单的增删改查语法小结
2016/08/31 PHP
thinkPHP模板中for循环与switch语句用法示例
2016/11/30 PHP
PHP基于openssl实现的非对称加密操作示例
2019/01/11 PHP
ExtJS 简介 让你知道extjs是什么
2008/12/29 Javascript
jquery select下拉框操作的一些说明
2010/04/02 Javascript
javascript利用初始化数据装配模版的实现代码
2010/11/17 Javascript
分享一个asp.net pager分页控件
2012/01/04 Javascript
文档对象模型DOM通俗讲解
2013/11/01 Javascript
jquery中的过滤操作详细解析
2013/12/02 Javascript
javascript中的作用域和上下文使用简要概述
2013/12/05 Javascript
javascript中的undefined和not defined区别示例介绍
2014/02/26 Javascript
让JavaScript的Alert弹出框失效的方法禁止弹出警告框
2014/09/03 Javascript
jQuery点击导航栏选中更换样式的实现代码
2017/01/23 Javascript
bootstrap table实现点击翻页功能 可记录上下页选中的行
2017/09/28 Javascript
mint-ui的search组件在键盘显示搜索按钮的实现方法
2017/10/27 Javascript
基于vue-cli 打包时抽离项目相关配置文件详解
2018/03/07 Javascript
如何为你的JS项目添加智能提示与类型检查详解
2019/03/12 Javascript
vue组件中iview的modal组件爬坑问题之modal的显示与否应该是使用v-show
2019/04/12 Javascript
JS通过ajax + 多列布局 + 自动加载实现瀑布流效果
2019/05/30 Javascript
vue循环数组改变点击文字的颜色
2019/10/14 Javascript
python爬虫获取新浪新闻教学
2018/12/23 Python
Python Pandas 转换unix时间戳方式
2019/12/07 Python
Sunglasses Shop德国站:欧洲排名第一的太阳镜网站
2017/08/01 全球购物
英国第一家领先的在线处方眼镜零售商:Glasses Direct
2018/02/23 全球购物
美国网上书店:Barnes & Noble
2018/08/15 全球购物
PHP开发工程师面试问题集锦
2012/11/01 面试题
经济与贸易专业应届生求职信
2013/11/19 职场文书
商业计算机应用专业自荐书
2014/06/09 职场文书
商铺消防安全责任书
2014/07/29 职场文书
村当支部个人对照检查材料思想汇报
2014/10/06 职场文书
质监局领导班子践行群众路线整改方案
2014/10/26 职场文书
2014小学教师个人工作总结
2014/11/10 职场文书
解决 redis 无法远程连接
2022/05/15 Redis