侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

JavaScript面向对象中接口实现方法详解

前端  /  管理员 发布于 4年前   390

本文实例讲述了JavaScript面向对象中接口实现方法。分享给大家供大家参考,具体如下:

接口是面向对象编程的基础,它是一组包含了函数型方法的数据结构,与类一样,都是编程语言中比较抽象的概念。比如生活中的接口,机顶盒,人们利用它来实现收看不同频道和信号的节目,它犹如对不同类型的信息进行集合和封装的设备,最后把各种不同类型的信息转换为电视能够识别的信息。在编程语言中的接口,实际上是不同类的封装并提供统一的外部联系通道,这样其他对象就可以利用接口来调用不同类的成员了。

――整理自《jQuery开发从入门到精通》

接口的概念

构造函数(类)是具体的实现,接口是类的约定。API接口(应用程序接口)、人机交互接口、电源接口、USB接口等虽然用途不同,功能各异,但是都包含一个共同的特性:约定、规范。可以说,接口就是一张契约和合同,它约定了设计者和使用者都必须遵循的要求。

接口承诺了具体类应该事先的功能。

举一个很有必要的例子,在java中实现接口,比如下面的代码:

interface Base{ void function1(); void function2(); void function3();}

Base接口承诺了3个基本功能:function1()、function2()、function3()。这个接口就像是一份合同,在甲方(调用类的用户)和乙方(定义类的开发人员)之间约定。

乙方负责实现接口约定的功能。功能的实现就是所谓的类。如下实例:

class App implements Base  // 定义一个App类,用这个类来实现接口Base

类App将遵照接口的约定。专业来说就是,应用类App继承Base接口类。

它的具体实现如下:

class App implements Base{ void function1(){  System.out.println("I am fun1"); } void function2(){  System.out.println("I am fun2"); } void function3(){  System.out.println("I am fun3"); }}

这样,乙方实现了这个接口,而甲方也应该来按照接口的约定去使用类App就行了。

所以说,接口(interface)和类(class),实际上都是相同的数据结构。

在接口中可以声明属性,方法,事件,类型,但不能声明变量,且不能设置被声明成员的具体值(功能实现)。

也就是说,接口只能定义成员,不能给定义的成员赋值。而接口作为它的继承类或派生类的约定,继承类或派生类共同完成接口属性、方法、事件、类型的实现。在接口和实现类之间,不管是方法名还是属性调用顺序上都应保持一致。

接口的目的就是约束编码,促使代码规范,对于强类型语言是必须的,也是非常重要的环节。但是对于JavaScript弱类型语言来说,严格的类型检查会束缚JavaScript的灵活性。很多前端开发人员根本不用接口,但不会影响脚本的设计。

使用接口的好处:降低对象间的耦合度,提高代码的灵活性。学会使用接口,能够让手中的函数变得灵巧,这在大型开发中是很重要的。

对于JavaScript来说,本身不支持接口功能,没有提供内置方法。但是人工设计一个额外的接口程序,又会对程序的性能产生影响。项目越大,这种开销越大。所以,用不用接口可以遵循两个条件:

① 项目大小,如果是一个框架,使用接口在一定程度上会提高程序的性能。如果是简单的应用,就不必使用接口了。

② 如果对JavaScript接口比较熟练,多用接口也可以,如果担心过多使用接口影响性能,则可以在考虑产品发布前,清除接口功能模块,或者设置接口的执行条件。防止它被频繁执行,影响性能。

接口的实现

JavaScript中并不支持接口,但是我们可以模仿其他语言,来定义接口。

下面来规划接口结构的设计和检测功能的实现:

(1) 设计一个接口辅助的类结构,这个构造函数相当于一个过滤器,用于在接口实例化过程中,检测初始化参数是否合法。如果符合接口设计标准,则把第2个参数中每个方法名和参数个数以数组元素的形式输入接口内部属性methods。在输入前分别检测每个参数类型是否符合规定。同时检查参数是否存在残缺,并即时以0补齐参数。

function Interface(name,methods){ // 接口辅助类,参数包括接口实例的名称和方法集 if(arguments.length!=2){ // 如果参数个数不等于2,抛出异常。  throw new Error('标准接口约定,需要两个参数'); } this.name = name; // 存储第一个参数值,实例化后就是接口实例的名称 this.methods = []; // 接口实例的方法存储器 if(methods.length < 1){ // 如果第二个参数的元素个数为0,说明是空数组,抛出异常。  throw new Error('接口的第二个参数不能为空'); } for(var i = 0; i < methods.length; i++){ // 开始对第2个参数的元素进行遍历检测  var item = methods[i];  if(typeof item[0] !== 'string') { // 如果第二个参数的第一个元素不是string类型,抛出异常   throw new Error("接口约定的第一个参数应为字符串");  }  if(item[1]&&typeof item[1] !== 'number'){ // 如果第二个参数有第二个元素,且第二个元素不是number类型,抛出异常   throw new Error('接口约定的第个参数应为数值');  }  if(item.length == 1){ // 如果第二个参数只有一个元素,那么手动给它添加第二个元素 0   item[1] = 0;  }  this.methods.push(item); // 把符合规定的方法存储到数组存储器中。 }}

(2) 为接口辅助类 Interface 定义一个方法 implements,该方法将检测实现类是否符合接口实例的约定。它至少包含两个参数,第1个参数o表示实现类,第2个参数及其后面的参数表示该类将要实现的接口标准。也就是说,可以为一个类指定多个接口约定,这样就可以更灵活的分类设计接口实例。然后遍历第二个及其后面的所有参数,在循环结构中,先洁厕接口是否为接口标准的实例,否则就会抛出异常。再从接口实例的方法存储器中逐一读取方法名,填入类中来验证类的方法是否符合接口实例设置的标准,验证包括方法名、function类型和参数个数。如果有问题,立即抛出异常。

Interface.implements = function(o){ // 用于检测类方法是否符合接口实例的约定 ,此处的o,将来会是类中的this if(arguments.length<2){ // 检测该方法传递的数值是否符合规定  throw new Error("接口约定类应包含至少两个参数。"); } for(var i=1;i

(3) 实例化接口标准,Interface 接口仅仅是个构造函数,也就是个框架协议,还没有制定类应该遵循的具体标准。框架协议中,已经设计好了监测逻辑,一旦实例化接口,并指明类应遵守的约定,那么应用该标准的实例的类就必须准守。下面根据Interface接口标准定义了6个具体的接口实例。

// 设置接口的不同实现实例var Get = new Interface("Get",[["get",0]]);var Set = new Interface("Set",[["set",1]]);var Saying = new Interface("Saying",[["saying",1]]);var Base = new Interface("Base",[["get",0],["set",1]]);var Base1 = new Interface("Base1",[["set",1],["get",0]]);var Base2 = new Interface("Base2",[["get",0],["set",1],["saying",1]]);

(4) 在类中定义应该实现的标准,即类应该遵循的接口约定。

// 创建一个木驴类function Neddy(){ this.name = ''; Interface.implements(this,Base,Get,Set); // 让木驴类实现接口的实例,可以指定多个,也可以只有一个。}// 按照接口实例来定义 两个方法get,setNeddy.prototype.get = function(){ return this.name;}Neddy.prototype.set = function(name){ this.name = name;}

(5) 在类中设置了多个接口实例,我们来进行检测

// 检测接口实现var neddy = new Neddy();neddy.set("Testing");console.log(neddy.get()); // Testing

成功完成接口的应用,这里,如果在Neddy类中,我们让它实现的接口实例和 Neddy.prototype中给类定义的方法不统一,或者接口与接口之间有冲突,就会抛出异常。比如我们可以修改Neddy中的接口实现,再给它添加一个接口实例Base2,就会报异常,因为我们没有按照接口的协议,给Neddy添加saying()方法。

上面的举例只是用js来模拟实现接口功能,在实际开发中,我们需要根据不同的需求,开发不同的接口。

扩展知识 :

检测函数的参数列表一般有三种形式

  • ① arguments.callee.length
  • ② 函数名.length
  • ③ arguments.length

其中 ① 和 ② 是一样的,③ 视具体情况而定。
一般函数声明式的定义有个默认属性name继承自Object ,举例如下:

function fn(x,y){  console.log(fn.name); // fn  console.log(arguments.callee.name); // fn  console.log(fn.length); // 2  console.log(arguments.callee.length); // 2  console.log(arguments.length); // 视具体情况而定}fn(1,2,3); // 分别输出 fn fn 2 2 3

为了说明上面接口检测参数长度 o[method].length  的问题 ,举例如下:

function A(){}A.prototype.say = function (x,y,z,o) {}var a = new A();console.log(a['say'].length); // 4

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

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

您可能感兴趣的文章:

  • javascript面向对象创建对象的方式小结
  • javascript面向对象三大特征之多态实例详解
  • javascript面向对象三大特征之继承实例详解
  • javascript面向对象三大特征之封装实例详解
  • 浅谈JavaScript面向对象--继承
  • JavaScript碎片―函数闭包(模拟面向对象)
  • JS实现面向对象继承的5种方式分析
  • JS面向对象基础讲解(工厂模式、构造函数模式、原型模式、混合模式、动态原型模式)
  • JS面向对象编程详解
  • JS 面向对象之神奇的prototype
  • javascript面向对象程序设计实践常用知识点总结


  • 上一条:
    IE11下处理Promise及Vue的单项数据流问题
    下一条:
    Vue webpack 项目自动打包压缩成zip文件的方法
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 使用 Alpine.js 排序插件对元素进行排序(0个评论)
    • 在js中使用jszip + file-saver实现批量下载OSS文件功能示例(0个评论)
    • 在vue中实现父页面按钮显示子组件中的el-dialog效果(0个评论)
    • 使用mock-server实现模拟接口对接流程步骤(0个评论)
    • vue项目打包程序实现把项目打包成一个exe可执行程序(0个评论)
    • 近期文章
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • Laravel 11.15版本发布 - Eloquent Builder中添加的泛型(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-11
    • 2018-03
    • 2018-04
    • 2018-05
    • 2018-06
    • 2018-09
    • 2018-11
    • 2018-12
    • 2019-02
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2021-04
    • 2021-05
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客