总结继承的几种方式

简单总结继承的几种方式

JavaScript作为一门弱类型的语言,本着精简的原则,它取消了类的概念,只有对象的概念,

更是有万物皆对象的说法。在基于类的面向对象方式中,对象(object)依靠类(class)来产生。

而在基于原型的面向对象方式中,对象(object)则是依靠构造器(constructor) 利用 原型(prototype)

构造出来的。而JavaScript语言正是如此,它是通过一种叫做原型(prototype)的方式来实现面向对象编程的。

它和其他的面向对象类编程语言一样,只是它的实现方式不同而已,或者说他们采用了不同的面向对象设计哲学。

那么下面就让我们来简单总结一下继承的几种方式:

  1. 扩展原型对象实现继承

构造函数有一个 prototype 属性,指向的就是原型对象,通过给原型对象添加属性和方法,让构造函数的实例

都可以访问到,从而实现继承

function Animal(name,color,say){this.name = name;this.color = color;this.say = function(){console.log('喵喵喵');}
}var cat = new Animal('cat','white');
// 如果给Animal的prototype属性上添加个 cry 方法 ,那么实例对象 cat将也会有 cry方法 
Animal.prototype.cry = function(){console.log('呜呜呜');
}
  1. 替换原型对象实现继承 (常用类型)
  • 为什么会有该方式呢?
    其实上面扩展原型对象的方法已经很方便了,但是为什么我们还需要使用该方式呢?试想一下,
    当我们需要给构造函数的原型对象添加许多属性和方法的时候,岂不是要写很多冗余(重复)的代码。例如上面的例子
    看下面代码:

        // 我们要给 构造函数Animal 添加很多的方法 即:Animal.prototype.aaa = function(){};Animal.prototype.bbb = function(){};Animal.prototype.ccc = function(){};Animal.prototype.ddd = function(){};Animal.prototype.eee = function(){};......  // 诸如这样的话,代码就显得不那么优雅,高效了吧。
  • 实现方式?
    重新给构造函数的prototype属性(原型对象)赋值,指向一个全新的对象,在这个对象中添加属性和方法,注:
    一定要添加一个constructor属性,并且指向构造函数本身 具体看代码:

        Animal.prototype = {// 一定要指明constructor属性,不然的话,会根据原型链查找一直到Object.prototypeconstructor : Animal;  saying : function(){},crying : function(){},doing : function(){}......}
  1. 混入继承
  • 混入继承的使用场景:已知对象 o1, o2, 需要把 o1中的功能(属性方法)拷贝到 o2 中去
  • 实现方式 :用 for...in... 对 o 进行遍历(可以将混入继承的模式封装成函数),如下所示

      // target : 目标对象(接收数据的对象)// source : 接收对象 (数据从哪个对象中来)function mixin(target,source){for(var key in source){target[key] = source[key];}return target;}
  • 原理其实很简单,jQuery中的$.extend 方法利用的就是混入继承的原理

  1. 原型 + 混入继承
  • 本质上就是对混入继承的一次运用
  • 只不过目标对象为原型对象而已

          // 运用上面封装的混入继承的函数  将对象{a:10,b:20,c:function(){}}的功能考本到Animal原型对象上去mixin(Animal.prototype, {a:10,b:20,c:function(){}} );  // 还可以 这样操作 给Animal构造函数 的原型对象添加一个extend方法,在该方法中调用mixin函数,这样的话也可以实现Animal.prototype.extend = function(){mixin(Animal.prototype, source);}// 不过两种方法没有本质之差,看大家易于接受哪个了
  1. 经典继承 —> 道格拉斯《JavaScript语言精粹》中提到的一种继承模型
  • 实现的功能:已知一个对象 o1 需要创建一个新的对象 o2 ,这个新的对象需要继承自对象 o1,代码如下:

        // 可以将经典继承 封装成一个函数function create(o){function F(){};    // 创建一个构造函数F.prototype = o;   // 将F 的原型指向 对象 o;return new F();    // 将 构造函数的实例 返回出去,这样的话 F的实例对象,就会继承自 o}var o2 = create(o1);  // 即:o2 继承于 o1 ;  o2.__proto__ = o1;
  • 使用场景 :要创建一个对象(不需要关心构造函数),新对象需要继承自另一个指定的对象
  • ES5中 :Object.create( ) 的实现原理就源自于经典继承

  1. 借用构造函数 实现继承
  • 先看一下代码 再解释:

      // 需要两个构造函数function Person(name,age,gender){  this.name = name;this.age = age;this.gender = gender;}// function Student(name,age,){//  this.name = name;// this.age = age;//  this.gender = gender;// }// 这样的话 name,age 属性都一样,就会产生重复的代码 我们可以巧妙的利用call 来简单的实现function Student(name,age){Person.call(this,name,age);     // 其实就是用 call的方法,call借用Person的功能this.gender = gender;}
    • 借用Person中的构造函数的功能,this表示构造函数的实例,即Student的实例对象可以继承name,age属性;
    • 借用构造函数实现继承,子构造函数借用父构造函数来完成,给子类Student的实例添加属性
    • 注意:由于要借用父类构造函数,所以父类构造函数的功能对子类对象要适用,例如下面情况就最好不用call

      // 需要两个构造函数
      function Person(name,age,gender){  this.name = name;this.age = age;this.gender = gender;
      }
      // function Student(name,age,){
      //  this.name = name;
      // this.age = age;
      // }
      function Student(name,age){Person.call(this,name,age);     
      }
  • 上述情况,就最好不要使用call来借用父类构造函数Person的功能了,因为,gender属性是Student子类构造函数
    并不需要的,这样的话,就会在Student中产生不必要的属性和方法,如果子类函数还要有gender方法的话,那么就会和之前的产生冲突,交叉污染
  • 其他情况:遇到需要实现功能,该对象上没有这个功能,可以适当地去寻找已经有功能的对象

转载于:https://www.cnblogs.com/guoqi77/p/Q_Inherit.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/372070.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Oracle SQL精妙SQL语句讲解(二)

- 如果存在就更新,不存在就插入用一个语句实现 DROP TABLE t_mg; CREATE TABLE t_mg(code VARCHAR2(10), NAME VARCHAR2(10)); SELECT * FROM t_mg; MERGE INTO t_mg a USING (SELECT the code code, the name NAME FROM dual) b ON (a.code b.code) WHEN M…

Spring Security –在一个应用程序中有两个安全领域

这篇博客文章主要是关于Spring Security配置的。 更具体地说,它打算显示如何在一个Web应用程序中配置两个不同的安全领域。 第一安全领域是针对浏览器客户端的。 它使我们能够在登录页面中登录并访问受保护的资源。 第二安全领域旨在处理来自android应用程序的REST…

基于Activiti工作流引擎实现的请假审核流程

概要 本文档介绍的是某商用中集成的Activiti工作流的部署及使用,该框架用的Activiti版本为5.19.0。本文档中主要以一个请假流程为例子进行说明,该例子的流程图如下: 这是一个可以正常运作的工作流业务了,但是它也有不足的地方&…

linux编译ffmpeg成so,「ffmpeg」一 mac 环境下编译ffmpeg,生成so库文件

1.下载ffmpeg源码,官网,我这里直接采用git 方式下载:下载ffmpeg.png终端输入git命令:静静等待~最后下载的版本为3.4.6 。image.png这里注意一下,刚开始我用的ndk版本是ndk-17b,在编译该版本的ffmpeg时始终失败&#xf…

4Web Service中的几个重要术语

4.1WSDL: web service definition language 直译:Webservice定义语言 1.对应一种类型的文件.wsdl 2.定义了webservice的服务端与客户端应用交互传递请求和响应数据的格式和方式 3.一个webservice对应一个唯一的esdl文档 4.2SOAP: simple object access protocal 直译:简单对象访…

云端:亚马逊,谷歌应用引擎,Windows Azure,Heroku,Jelastic

您想在云端吗? 您有很多选择。 我已经评估或使用了许多方法,因此这里有几句话。 (当我使用Java时,我将包括一些与Java相关的注释,但大多数情况适用于所有(受支持的)语言。) 但是在深…

JS-字符串操作-替换

<!DOCTYPE HTML><html><head><meta http-equiv"Content-Type" content"text/html; charsetutf-8"><title>无标题文档</title><style>p { border:10px solid #ccc; background:#FFC; width:400px; padding:20px;…

linux下kegg注释软件,KEGG数据中全部代谢反应和代谢物注释信息的下载

# 加载函数与R包 -----------------------------------------------------------------library(KEGGREST)library(plyr)source("./RbioRXN-master/RbioRXN-master/R/get.kegg.all.R")source("./RbioRXN-master/RbioRXN-master/R/get.kegg.byId.R")## KEGG数…

java常见异常

算术异常类&#xff1a;ArithmeticExecption空指针异常类&#xff1a;NullPointerException 类型强制转换异常&#xff1a;ClassCastException 数组负下标异常&#xff1a;NegativeArrayException 数组下标越界异常&#xff1a;ArrayIndexOutOfBoundsException 违背安全原则异常…

Spring Security 3 Ajax登录–访问受保护的资源

我看过一些有关Spring Security 3 Ajax登录的博客&#xff0c;但是我找不到解决如何调用基于Ajax的登录的博客&#xff0c;匿名用户正在Ajax中访问受保护的资源。 问题 – Web应用程序允许匿名访问某些部分&#xff0c;并且某些部分是受保护的资源&#xff0c;需要用户登录。 …

测试环境下将centos6.8升级到centos7的操作记录(转)

在测试环境下安装openstack&#xff0c;由于在centos6下安装openstack&#xff0c;针对源的问题有很多&#xff0c;安装起来很不顺利&#xff01; 但是在centos7下安装却很顺利&#xff0c;所以考虑将服务器由centos6升级到centos7 这个我是在测试机中运行的&#xff0c;建议不…

linux运维选择题,初学Linux练习题

1、将/etc/issue文件中的内容转换为大写后保存至/tmp/issue.out文件中tr ‘a-z’ ‘A-Z’ < /etc/issue > /tmp/issue.out2、将当前系统登录用户的信息转换为大写后保存至/tmp/who.out文件中3、一个linux用户给root发邮件&#xff0c;要求邮件标题为”help”&#xff0c…

[转]Web Api系列教程第2季(OData篇)(二)——使用Web Api创建只读的OData服务

本文转自&#xff1a;http://www.cnblogs.com/fzrain/p/3923727.html 前言 很久没更新了&#xff0c;之前有很多事情&#xff0c;所以拖了很久&#xff0c;非常抱歉。好了&#xff0c;废话不多说&#xff0c;下面开始正题。本篇仍然使用上一季的的项目背景&#xff08;系列地址…

使用Spring 3 MVC处理表单

本文是有关Spring 3的一系列文章的一部分。该系列的上一篇文章可以在此处获得 。 在本文中&#xff0c;我们向Spring MVC迈出了又一步。 [此外&#xff1a; 术语MVC的创建者提供的pdf 。]从上一篇文章构建&#xff0c;让我们添加将“联系人”添加到应用程序所需的代码。 首先&a…

插入排序法之——直接插入排序、折半插入排序、希尔排序

// test20.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include<iostream> #include<vector> #include<string> #include<queue> #include<stack> #include<cstring> #include<string.h> #include<de…

linux idea 快捷键,Linux 下 IDEA 的 Ctrl+Alt+S

前言这是个困扰我一年多的问题&#xff0c;今天终于解决了……起因一年前将主系统换成 Arch Linux 后&#xff0c;其他一切正常就是 IDEA 的打开设置的快捷键 ctrlalts 失效&#xff0c;让我很是头疼。虽然不是很重要&#xff0c;但是对于我这种强迫症来说别提多难受了……我曾…

修改input的placeholder颜色

1、CSS选择器 因为每个浏览器的CSS选择器有所差异&#xff0c;所以需要针对每个浏览器做单独的设定。 ::-webkit-input-placeholder { /* WebKit browsers */ color: #999; } :-moz-placeholder { /* Mozilla Firefox 4 to 18 */ color: #999; } ::-moz-placeholder { /* Mozil…

解决Spring自动装配中的循环依赖

我认为这篇文章是在企业应用程序开发中使用Spring的最佳实践。 使用Spring编写企业Web应用程序时&#xff0c;服务层中的服务量可能会增加。 服务层中的每个服务可能会消耗其他服务&#xff0c;这些服务将通过Autowire注入。 问题&#xff1a;当服务数量开始增加时&#xff0…

01.MD5加密

namespace _01.MD5加密{ class Program { static void Main(string[] args) { //MD5加密就是给想要的密码或者其它字符加密 //如果字符串被加密成MD5值之后,是不可逆的. //字符串123 的MD5 64位加密形式是 202cb962ac59075b964b07152d234b70 Console.WriteLine("请输入需要…

C语言数字3转变字符 3 程序,大学c语言知识点总结

大学c语言知识点总结C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。一起来看看大学c语言知识点总结吧!大学c语言知识点总结1、编译预处理不是C语言的一部分&#xff0c;不再运行时间。C语言编…