深入js的面向对象学习篇——温故知新(一)
在学习设计模式前必须要知道和掌握的***。
为类添加新方法:
Function.prototype.method = function(name,fn) {
this.prototype[name] = fn;
} //改进版:支持链式调用 Function.prototype.method = function(name,fn) {
this.prototype[name] = fn;
return this;
}
函数是一等对象,可以存储在变量中,可以作为参数传给其他函数,可以作为返回值从其他函数传出,还可以再运行的时候进行构造。这正是用以构造传统面向对象框架的基础。
对象具有易变性。类方法可以在类实例创建之后再添加,实例仍然能够获得新添加的方法。个人觉得,这也是对象扩展的威力源泉。
一、接口
“针对接口,而不是实现编程”
接口提供了一种用以说明一个对象应该具备哪些方法的手段。既定的一批接口具有自我描述性,并能促进代码的重用。接口可以告诉程序员一个类实现了哪些方法,从而帮助其使用这个类。接口最实在的用途是什么?~一个程序员可以针对所需要的类定义一个接口,并转交给另一个程序员。第二个程序员可以随心所欲地编写自己的代码,只要他定义的类实现了那个接口就行。
当然接口也有弊端。比如额外的方法调用的开销无法避免。
而接口使用中的最大问题在于,无法强迫其他程序员遵守你定义的接口。不像其它语言(像java等,编译期间会因为接口继承后没有写实现而报错),javascript中必须用手工的办法保证某个类实现了一个接口(你可能对此不理解是什么意思,稍安,等下立马解释^_^)。如果项目的其他程序员不认真对待接口,那么这些接口的使用是无法得到强制性保证的。除非项目的所有人都同意使用接口并对其进行检查,否则接口的很多价值都无从体现。
解惑的时候到了,为什么前文说“javascript中必须用手工的办法保证某个类实现了一个接口”。事实上,javascript没有interface和implements关键字,也不在运行时对接口约定是否得到遵守进行检查。我们只能在javascript中模仿接口。一下介绍模仿接口的三种方法:注释法、属性检查法、鸭式辨型法。
① 注释法:
/*
interface Composite {
function add(child);
function remove(child);
function getChild(index);
} interface FormItem {
function sava();
}
*/ var compositeForm = function (id,method,action) {
....
}; compositeForm.prototype.add = function(child) {
....
}; compositeForm.prototype.remove = function(child) {
.....
};
这种方法易于实现,但是不会提供错误信息。
② 用属性检查模仿接口
/*
interface Composite {
function add(child);
function remove(child);
function getChild(index);
} interface FormItem {
function sava();
}
*/ var compositeForm = function(id,method,action) {
this.implementInterfaces = ['Composite','FormItem'];
......
}; function addForm(formInstance) {
if(!implements(formInstance,'Composite','FormItem')) {
throw new Error("Object does not implement a required interface.");
....
}
} function implement(object) { //检查接口是否被实现
for(var i = 0;i < arguments.length;i++) {
var interfaceName = arguments[i];
var interfaceFound = false;
for(var j = 0;j < object.implementsInterfaces.length;j++) {
if(interfaceName == object.implementsInterfaces[j]) {
interfaceFound = true;
break;
}
}
if(!interfaceFound) {
return false;
}
}
return true;
}
优点:它对所有实现的接口提供了文档说明。如果需要的接口不在一个类宣称支持的接口之列,你会看到错误消息。通过利用这些错误,你可以强迫其它程序员声明这些接口。
缺点:它并未确保类真正实现自称实现的接口。很可能,只是有了这个接口的实现声明,方法体忘记写了,一个空的方法体造成了假象。
③ 用鸭式辨型模仿接口
思想:类是否声明自己支持哪些接口不重要,只要它具有这些接口中的方法就行。“像鸭子一样走路并且嘎嘎叫的就是鸭子”。如果一个对象具有与接口定义的方法同名的所有方法,那么就可以认为它实现了这个接口。(个人觉得,这有点像客户端检测机制,我们不是去判断浏览器的类型,而是转而判断浏览器是否支持此项功能^_^换个角度思考问题往往有事半功倍之效。)
缺点:类并不声明自己实现了哪些接口,这降低了代码的可重用性,并且也缺乏其他两种方法的自我描述性。
个人觉得,最好的就接口实现时方法一和方法三的结合。也就是可读性和保证性相结合。
var Composite = new Interface('Composite',['add','remove','getChild']);
var FormItem = new Interface('FormItem',['save']); var CompositeForm = function(id,method,action) {
....
}; function addForm(formInstance) {
Interface.ensureImplements(formInstance,Composite,FormItem);
....
} var Interface = function(name,methods) {
if(arguments.length != 2) {
throw new Error("...........");
} this.name = name;
this.methods = [];
for(var i = 0;i < methods.length;i++) {
if(typeof methods[i] !== 'string') {
throw new Error("..........");
}
this.methods.push(methods[i]);
}
}; Interface.ensureImplements = function() {
if(arguments.length < 2) {
throw new Error("....");
} for(var i = 1,len = arguments.length;i < len;i++) {
var interface = arguments[i];
if(interface.constructor !== Interface) {
throw new Error("....");
} for(var j = 0,methodsLen = interface.methods.length;j < methodsLen;j++) {
var method = interface.methods[j];
if(!object[method]||typeof object[method] !== 'function') {
throw new Error("....");
}
}
}
}
接口在运用设计模式实现复杂系统的时候最能体现其价值。降低了对象间的耦合程度。在大型项目中,易于程序员的合作,如果你知道测试中的桩测试,你对此用个空方法体进行占位,提供API,无疑会使程序员间的合作开发更便捷。
深入js的面向对象学习篇——温故知新(一)的更多相关文章
- 深入js的面向对象学习篇(继承篇)——温故知新(三)
写这篇有关继承的文章时,突然想起,几天前的面试.因为习惯在学习知识的时候加上自己的理解,很喜欢用自己话来解释,于是乎当面试被问起继承原理时,噼里啪啦一大堆都是自己组织的话,(也可能是因为个人紧张.外加 ...
- 深入js的面向对象学习篇(封装是一门技术和艺术)——温故知新(二)
下面全面介绍封装和信息隐藏. 通过将一个方法或属性声明为私用的,可以让对象的实现细节对其它对象保密以降低对象之间的耦合程度,可以保持数据的完整性并对其修改方式加以约束.在代码有许多人参与设计的情况下, ...
- 【js】面向对象学习资料
1.面向对象模式: https://m.jb51.net/article/74549.htm 2.面向对象基础篇 http://www.cnblogs.com/chiangchou/p/js-oop1 ...
- js之面向对象----封装篇
学习了一天的面向对象总结一下,共分为三类 - -! 老规矩 第一部分是概念性知识!!! 面向对象编程,我们可以把他想象成我们在造人.一个对象便是一个人,这个人有胳膊有腿,这便是一个对象的属性或者方法. ...
- js面向对象学习 - 对象概念及创建对象
原文地址:js面向对象学习笔记 一.对象概念 对象是什么?对象是“无序属性的集合,其属性可以包括基本值,对象或者函数”.也就是一组名值对的无序集合. 对象的特性(不可直接访问),也就是属性包含两种,数 ...
- js学习篇1--数组
javascript的数组可以包含各种类型的数据. 1. 数组的长度 ,直接用 length 属性; var arr=[1,2,3]; arr.length; js中,直接给数组的length赋值是会 ...
- js面向对象学习
纯属笔记,加强记忆,不是教程,欢迎纠错,没有逻辑,不太适合学习使用. -------------- 继承多态等太多概念难以理解,还是从实践中慢慢学吧!争取能大致看懂网上的开源的代码. -------- ...
- 我的JS 中级学习篇
在codefordream上进入中级学习后,感觉立马从js的基础学习往前跳了好远,上面的东西好像都是第一次看到一样.这时候才发现,说来也曾接触过js,但是这时候才发现对js的认识就停在知道两点:js中 ...
- JavaScript--我发现,原来你是这样的JS:面向对象编程OOP[2]--(创建你的那个对象吧)
一.介绍 我们继续面向对象吧,这次是面向对象编程的第二篇,主要是讲创建对象的模式,希望大家能从博客中学到东西. 时间过得很快,还是不断的学习吧,为了自己的目标. 二.创建对象 1.前面的创建对象方式 ...
随机推荐
- Linux 命令 - killall: 通过进程名向进程发送信号
命令格式 killall [-Z CONTEXT] [-u USER] [ -eIgiqrvw ] [ -SIGNAL ] NAME... killall -l, --list killall -V, ...
- 开发Android应用 提升性能的小技巧
前 言 2015年,Android OS 目前在手机操作系统的市场占有率已达59%,权威机构预计,Android市场占有率在2016年将达到63%,由于Android的开放性,未来占有率还将不断增加, ...
- [Entity Framework] MySQL @ Entity Framework 6
原文 [Entity Framework] MySQL @ Entity Framework 6 要让MySQL能够用EF6,我花了一点时间,在此记录一下 安装元件 在设定档加入Provider 安装 ...
- 创建featureclass,为它赋别名,并移动到数据集下
if (pOutFtrClass == null) { //continue; //创建featureclass //得到规范的字段集 IFields pFields = pFeatureClass. ...
- 2016年11月ACM/ICPC亚洲区北京赛赛后总结
2016年11月12到11月13为期两天的比赛,这是我们这个对第一次去打亚洲区域赛,经过这次比赛,我认识到了自己与别人的差距,也许我们与别人的起点不同,但这不是理由. 这次的比赛12号的热身赛两点开始 ...
- QMessageBox 在MAC下更加自然
说明 在MAC写过QT程序的程序员应该都知道,QT默认的QMessageBox没有MAC系统的效果,在网上找到了一篇关于这方面的文章,但是这篇文章写的有个缺点,就是使用信号的方式,使用起来很不方便. ...
- Using OpenCV Java with Eclipse
转自:http://docs.opencv.org/trunk/doc/tutorials/introduction/java_eclipse/java_eclipse.html Using Open ...
- jQuery父级以及同级元素查找介绍
父级以及同级元素的查找在使用过程中还是蛮频繁的,下面为大家介绍下jQuery是如何实现的,感兴趣的朋友可以参考下: jQuery.parent(expr) 找父亲节点,可以传入expr进行过滤,比如$ ...
- css3选择器一
在HTML中,通过各种各样的属性可以给元素增加很多附加的信息,了解和掌握css3一些的选择器,是很有必要的. 属性选择器示例: <div><a href="xxx.pdf& ...
- phpstorm配置取消掉63342
http://ask.csdn.net/questions/171665