方法链一般适合对一个对象进行连续操作(集中在一句代码)。一定程度上可以减少代码量,缺点是它占用了函数的返回值。

一、方法体内返回对象实例自身(this)

  1. function ClassA(){
  2. this.prop1 = null;
  3. this.prop2 = null;
  4. this.prop3 = null;
  5. }
  6. ClassA.prototype = {
  7. method1 : function(p1){
  8. this.prop1 = p1;
  9. return this;
  10. },
  11. method2 : function(p2){
  12. this.prop2 = p2;
  13. return this;
  14. },
  15. method3 : function(p3){
  16. this.prop3 = p3;
  17. return this;
  18. }
  19. }

定义了function/类ClassA。有三个属性/字段prop1,prop2,prop3,三个方法methed1,method2,method3分别设置prop1,prop2,prop3。

链式调用如下:

  1. var obj = new ClassA();
  2. obj.method1(1).method2(2).method3(3); // obj -> prop1=1,prop2=2,prop3=3

可以看到对obj进行了连续三次操作,只要愿意ClassA的N多方法都这样定义,调用链会一直延续。

该方式缺点是链方法唯一地绑定于一种对象类型(ClaaaA),按这种方式实现链式操作,每定义一个类,其方法体中都要返回this。第二种方式可以解决这个问题。

二、对象传入后每次调用返回函数自身

  1. /**
  2. * chain 最易读版
  3. * @param {Object} obj
  4. */
  5.  
  6. function singleChain1(obj){
  7. function chain(){
  8. if (arguments.length == 0){
  9. return chain.obj;
  10. }
  11. var methodName = arguments[0], methodArgs = [].slice.call(arguments,1);
  12. chain.obj[methodName].apply(chain.obj,methodArgs);
  13. return chain;
  14. }
  15. chain.obj = obj;
  16. return chain;
  17. }
  18. /**
  19. * chain 易读版
  20. * @param {Object} obj
  21. */
  22. function singleChain2(obj){
  23. return function(){
  24. var Self = arguments.callee; Self.obj = obj;
  25. if(arguments.length==0){
  26. return Self.obj;
  27. }
  28. var methodName = arguments[0], methodArgs = [].slice.call(arguments,1);
  29. Self.obj[methodName].apply(Self.obj,methodArgs);
  30. return Self;
  31. }
  32. }
  33. /**
  34. * chain 精简版
  35. * @param {Object} obj
  36. */
  37. function singleChain3(obj){
  38. return function(){
  39. var Self = arguments.callee; Self.obj = obj;
  40. if(arguments.length==0){
  41. return Self.obj;
  42. }
  43. Self.obj[arguments[0]].apply(Self.obj,[].slice.call(arguments,1));
  44. return Self;
  45. }
  46. }

使用:

  1. /**
  2. * chain 精简版
  3. * @param {Object} obj
  4. */
  5. function chain(obj){
  6. return function(){
  7. var Self = arguments.callee; Self.obj = obj;
  8. if(arguments.length==0){
  9. return Self.obj;
  10. }
  11. Self.obj[arguments[0]].apply(Self.obj,[].slice.call(arguments,1));
  12. return Self;
  13. }
  14. }
  15.  
  16. //定义的function/类ClassB
  17. function ClassB(){
  18. this.prop1 = null;
  19. this.prop2 = null;
  20. this.prop3 = null;
  21. }
  22. ClassB.prototype = {
  23. method1 : function(p1){
  24. this.prop1 = p1;
  25. },
  26. method2 : function(p2){
  27. this.prop2 = p2;
  28. },
  29. method3 : function(p3){
  30. this.prop3 = p3;
  31. }
  32. }

注意ClassB的method1,method2,method3中不再返回this了。

链式调用如下:

  1. var obj = new ClassB();
  2. chain(obj)('method1',4)('method2',5)('method3',6); // obj -> prop1=4,prop2=5,prop3=6

第一种方式3次调用后返回了对象自身,这里使用一个空"()"取回对象

  1. // result -> prop1=4,prop2=5,prop3=6
  2. var result = chain(obj)('method1',4)('method2',5)('method3',6)();

这种方式写类时方法体中无须返回this,且可以对任何对象进行链式调用。

接下来介绍YUI中Node类实现的链式调用方法。

在YUI3中,Node类的基础是Dom,很多Node类的方法都是调用Dom类的同名方法,如上面提到的setAttribute、setStyle等,

在Dom类源码中也未设置返回本对象,在Node类提供了importMethods方法来导入Dom中相同的方法并支持链式调用。示例代码如下:

  1. //Dom类及静态方法
  2. function Dom(id){
  3. this.dom = document.getElementById(id);
  4. }
  5.  
  6. Dom.setStyle = function(node,name,value){
  7. node.dom.style[name] = value;
  8. }
  9.  
  10. Dom.setAttribute = function(node,name,v){
  11. node.dom.setAttribute(name,v);
  12. }
  13.  
  14. //Node类
  15. function Node(id){
  16. this.dom = document.getElementById(id);
  17. }
  18.  
  19. //添加方法的函数
  20. Node.addMethod = function(method,fn){//,context
  21.  
  22. Node.prototype[method] = function(){
  23. var me = this;
  24. //Array.prototype.unshift.call(arguments,me);
  25. //or
  26. arguments = Array.prototype.slice.call(arguments);
  27. arguments.unshift(me);
  28. fn.apply(me,arguments);
  29. return me;
  30. }
  31.  
  32. }
  33.  
  34. //批量添加方法的函数
  35. Node.importMethods = function(host,methods){
  36. for(var i in methods){
  37. var m = methods[i];
  38. var fn = host[m];
  39. Node.addMethod(m,fn);
  40. }
  41. }
  42.  
  43. //定义需要给Node类添加的方法名 列表
  44. var methods = ['setStyle','setAttribute'];
  45.  
  46. //使用批量添加方法的函数将Dom中的相关方法添加到Node中
  47. Node.importMethods(Dom,methods);
  48.  
  49. //可以在Node中进行链式调用
  50. var n = new Node('log').setStyle('border','2px solid red').setAttribute('t',22);

在实际使用中,可以对原有的对象方法(如Dom中的方法)扩展到另一个类中(如Node类),在Node类中进行链式调用。当然也可以使用同样的方式(importMethods)不扩展而是覆盖Dom中的方法。

转自:http://houfeng0923.iteye.com/blog/1139525

javascript链式调用实现方式总结的更多相关文章

  1. javascript 链式调用+构造函数

    前几天面试,有一个问题是使用构造函数实现链式调用,后面查看了一些简单的资料,整理一下 首先,先说一下JS 中构造函数和普通函数的区别,主要分为以下几点 1.构造函数也是一个普通函数,创建方式和普通函数 ...

  2. Javascript链式调用案例

    jQuery用的就是链式调用.像一条连接一样调用方法. 链式调用的核心就是return this;,每个方法都返回对象本身. 下面是简单的模拟jQuery的代码, <script> win ...

  3. 一种javascript链式多重继承的方式(__proto__原型链)

    var a=function(){this.foo='bar';} a.prototype={b:1}; var aa=function(){} aa.prototype={c:2,__proto__ ...

  4. js链式调用 柯里化

    var d = 1; d.add(2).add(3).add(4) //输出10 写出这个add函数 Number.prototype.add = function(x){ return this + ...

  5. JavaScript动态加载script方式引用百度地图API 拓展---JavaScript的Promise

    上一篇博客JavaScript动态加载script方式引用百度地图API,Uncaught ReferenceError: BMap is not defined 这篇文章中我接触到一个新的单词:Pr ...

  6. javascript方法链式调用和构造函数链式调用对比

    先说一下方法链:B的实例从A继承了A中的同名方法,如果B的方法重载了A中的方法,B中的重载方法可能会调用A中的重载方法,这种方法称为方法链. 构造函数链:子类的构造函数B()有时需要调用父类的构造函数 ...

  7. Android 异步链式调用设计

    本文讨论一下异步链式调用的设计与实现. 考虑如下情况: 情况1: 访问网络(或其他耗时的事情).通常的做法是: 1.显示一个ProgressDialog对话框,提示用户. 2.启动工作线程来执行耗时操 ...

  8. Scala 深入浅出实战经典 第51讲:Scala中链式调用风格的实现代码实战及其在Spark中应用

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  9. JavaScript 链式结构序列化详解

    一.概述 在JavaScript中,链式模式代码,太多太多,如下: if_else: if(...){ //TODO }else if(...){ //TODO }else{ //TODO } swi ...

随机推荐

  1. "windows 正在启动"

    xp 在cmd下使用了control userpasswords2 设定开机不需要密码之后,开机停留在“window正在启动”,无法进入.估计是设置的时候密码输入错误了( 并不会提示你错误:() 在停 ...

  2. USB Mass Storage学习笔记-STM32+FLASH实现U盘

    一.内容概述  采用STM32内部自带USB控制器外加大页NAND FLASH K9F1G08U0A实现一个128M的U盘. 1.STM32的USB控制器 STM32F103的MCU自带USB从控制器 ...

  3. Struts2+Spring+Ibatis集成合并

    上一篇博客讲述了Struts2+Spring的集成合并,主要是利用了一个中间jar包,这篇博客在加上Ibatis持久层框架,三个框架进行合并.其中Struts2和Spring部分和前边的一样,主要是讲 ...

  4. Struts2(三)——数据在框架中的数据流转问题

    一款软件,无在乎对数据的处理.而B/S软件,一般都是用户通过浏览器客户端输入数据,传递到服务器,服务器进行相关处理,然后返回到指定的页面,进行相关显示,完成相关功能.这篇博客重点简述一下Struts2 ...

  5. strcpy与memcpy的区别

    strcpy和memcpy的区别 strcpy和memcpy都是标准C库函数,它们有下面的特点. strcpy提供了字符串的复制.即strcpy只用于字符串复制,并且它不仅复制字符串内容之外,还会复制 ...

  6. ubuntu WiFi: operation not possible due to RF-kill《转载》

    Some people have been experiencing WiFi problems with Ubuntu 10.10 since an update that happend just ...

  7. 搭建高可用mongodb集群—— 分片

    从节点每个上面的数据都是对数据库全量拷贝,从节点压力会不会过大? 数据压力大到机器支撑不了的时候能否做到自动扩展? 在系统早期,数据量还小的时候不会引起太大的问题,但是随着数据量持续增多,后续迟早会出 ...

  8. DataSet、DataTable、DataRow区别

     DataSet 表示数据在内存中的缓存. 属性 Tables  获取包含在 DataSet 中的表的集合. ds.Tables["sjxx"] DataTable 表示内存中数据 ...

  9. Java编程的23种设计模式

    设计模式(Design Patterns)                                   --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用. ...

  10. C#抓取网页内容

    学习材料一 <C#抓取网页数据分析> 抓取Web网页数据分析 HttpWebRequest 和 HttpWebResponse 的应用