对$函数你已经很熟悉了。它通常返回一个html元素或一个html元素的集合,如下:

  1. function$(){
  2. var elements = [];
  3. for(vari=0,len=arguments.length;i<len;++i){
  4. var element = arguments[i];
  5. if(typeof element ===”string”){
  6. element = document.getElementById(element);
  7. }
  8. if(arguments.length==1){
  9. return element;
  10. }
  11. elements.push(element);
  12. }
  13. return elements;
  14. }

但是,如果把这个函数改造为一个构造器,把那些元素作为数组保存在一个实例属性中,并让所有定义在构造器函数的prototype属性所指对象中的方法都返回用以调用方法的那个实例的引用,那么它就具有了链式调用的能力。我首先需要把这个$函数改为一个工厂方法,它负责创建支持链式调用的对象。这个函数应该能接受元素数组形式的参数,以便我们能够使用与原来一样的公用接口。

  1. (function(){
  2.  
  3. //use private class
  4. function _$(els){
  5. this.elements = [];
  6. for(vari=0,len=els.length;i<len;i++){
  7. var element = els[i];
  8. if(typeof element ===”string”){
  9. element = document.getElementById(element);
  10. }
  11. this.elements.push(element)
  12. }
  13. }
  14. //The public interface remains the same.
  15.  
  16. window.$ = function(){
  17. return new _$(arguments);
  18. }
  19. })();

由于所有对象都会继承其原型对象的属性和方法,所以我们可以让定义在原型对象中的那几个方法都返回用以调用方法的实例对象的引用,这样就可以对那些方法进行链式调用。想好这一点,我们现在就动手在_$这个私用构造函数的prototype对象中添加方法,以便实现链式调用

  1. (function(){
  2.  
  3. //use private class
  4.  
  5. function _$(els){
  6. //..省略之前上面的代码
  7. }
  8.  
  9. _$.prototype = {
  10. each:function(fn){
  11. for(var i=0,len=this.elements.length;i<len;i++){
  12. fn.call(this,this.elements[i]);
  13. }
  14. return this;
  15. },
  16.  
  17. show:function(prop,val){
  18. var that = this;
  19. this.each(function(el){
  20. that.setStyle("display”,”block");
  21. });
  22. return this;
  23. },
  24.  
  25. addEvent:function(type,fn){
  26. var add = function(el){
  27. if(window.addEventListener){
  28. el.addEventListener(type,fn,false);
  29. }else if(window.attachEvent){
  30. el.attachEvent("on"+type,fn);
  31. }
  32. };
  33.  
  34. this.each(function(el){
  35. add(el);
  36. });
  37. return this;
  38. }
  39. };
  40.  
  41. //The public interface remains the same.
  42.  
  43. window.$ = function(){
  44. return new _$(arguments);
  45. }
  46.  
  47. })();

但是如果某个库或者框架已经定义了一个$函数,那么我们的这个库会将其改写,有个简单的办法是在源码中为$函数另去一个名字。但是如果你是从一个现有的库获得的源码,那么每次代码库获取更新的版本后 你都得重新改名字,因此这个方案并不是很好。好的解决办法就是像下面一样添加一个安装器:

  1. window.installHelper = function(scope, interface) {
  2. scope[interface] = function() {
  3. return new _$(arguments);
  4. }
  5. };

用户可以这样去使用:

  1. installHelper(window, '$');
  2. $('example').show();

下面是一个更复杂的例子,它展示了如何把这种功能添加到一个事先定义好的命名对象中:

  1. // Define a namespace without overwriting it if it already exists.
  2. window.com = window.com || {};
  3. com.example = com.example || {};
  4. com.example.util = com.example.util || {};
  5.  
  6. installHelper(com.example.util, 'get');
  7.  
  8. (function() {
  9. var get = com.example.util.get;
  10. get('example').addEvent('click', function(e) {
  11. get(this).addClass('hello');
  12. });
  13. })();

有时候把方法连起来并不是一个好主意。链式调用很适合于赋值器方法,但对于取值器的方法,你可能会希望他们返回你要的数据而不是返回this。不过,如果你把链式调用作为首要目标,希望所有方法的使用方式保持一致的话,那么变通的方法还是有的:你可以利用回调技术来返回所要的数据下面有两个例子:其中API类使用了普通的取值器(它中断了调用链),而API2类则使用了回调方法:

  1. // Accessor without function callbacks: returning requested data in accessors.
  2. window.API = window.API || {};
  3. API.prototype = function() {
  4. var name = 'Hello world';
  5. // Privileged mutator method.
  6. setName: function(newName) {
  7. name = newName;
  8. return this;
  9. },
  10. // Privileged accessor method.
  11. getName: function() {
  12. return name;
  13. }
  14. }();
  15.  
  16. // Implementation code.
  17. var o = new API;
  18. console.log(o.getName()); // Displays 'Hello world'.
  19. console.log(o.setName('Meow').getName()); // Displays 'Meow'.
  20.  
  21. // Accessor with function callbacks.
  22. window.API2 = window.API2 || {};
  23. API2.prototype = function() {
  24. var name = 'Hello world';
  25. // Privileged mutator method.
  26. setName: function(newName) {
  27. name = newName;
  28. return this;
  29. },
  30. // Privileged accessor method.
  31. //通过把函数作为参数传入
  32. getName: function(callback) {
  33. callback.call(this, name);
  34. return this;
  35. }
  36. }();
  37.  
  38. // Implementation code.
  39. var o2 = new API2;
  40. o2.getName(console.log).setName('Meow').getName(console.log);
  41. // Displays 'Hello world' and then 'Meow'.

浅析 JavaScript 链式调用的更多相关文章

  1. JavaScript链式调用

    1.什么是链式调用? 这个很容易理解,例如 $('text').setStyle('color', 'red').show(); 一般的函数调用和链式调用的区别:链式调用完方法后,return thi ...

  2. 关于JavaScript中的setTimeout()链式调用和setInterval()探索

    http://www.cnblogs.com/Wenwang/archive/2012/01/06/2314283.html http://www.cnblogs.com/yangjunhua/arc ...

  3. JavaScript实现链式调用

    学习Jquery的时候,我们通常会看到链式调用的写法 $(window).addEvent('load', function(){ $('test').show().setStyle('color', ...

  4. JavaScript设计模式-8.链式调用

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  5. 《javascript设计模式》笔记之第六章:方法的链式调用

    这一章要实现的就是jQuery的那种链式调用,例子: $(this).setStyle('color', 'green').show(); 一:调用链的结构: 首先我们来看一下最简单的$()函数的实现 ...

  6. JavaScript中的链式调用

    链模式 链模式是一种链式调用的方式,准确来说不属于通常定义的设计模式范畴,但链式调用是一种非常有用的代码构建技巧. 描述 链式调用在JavaScript语言中很常见,如jQuery.Promise等, ...

  7. JavaScript设计模式——方法的链式调用

    方法的链式调用: (function() { //私有类 function _$ (els) { this.elements = []; for(var i = 0, len = els.length ...

  8. javascript学习(10)——[知识储备]链式调用

    上次我们简单的说了下单例的用法,这个也是在我们java中比较常见的设计模式. 今天简单说下链式调用,可能有很多人并没有听过链式调用,但是其实只要我简单的说下的话,你肯定基本上都在用,大家熟知的jQue ...

  9. js原生设计模式——2面向对象编程之js原生的链式调用

    技巧点:对象方法中返回当前对象就可以链式调用了,即方法中写return this; <!DOCTYPE html><html lang="en"><h ...

随机推荐

  1. Effective C++ 第二版 31)局部对象引用和函数内new的指针 32)推迟变量定义

    条款31 千万不要返回局部对象的引用, 不要返回函数内部用new初始化的指针的引用 第一种情况: 返回局部对象的引用; 局部对象--仅仅是局部的, 在定义时创建, 在离开生命空间时被销毁; 所谓生命空 ...

  2. [javascript]jsonp-function 代码段

    (function($1454395832823,arr_infoList /**/) { $1454395832823.push(' '); for(var i in arr_infoList) { ...

  3. ReportMachine 自定义代码 画细线

    ReportMachine 自定义代码 画细线 procedure Memo3_OnBeforePrint(Sender: TObject); begin Memo3.Text := inttostr ...

  4. IE兼容性小结(IE7及以上版本)

    缘由 在急速的互联网时代,原本ie系列的低版本浏览器就该淘汰了.可偏偏还是有很多xp系统ie7.8浏览器,这有让网站甚是苦逼.练就了一套新技术,原本以为能大展身手,可却在ie阵容中认怂了,不得不规规矩 ...

  5. 分享自己使用的在线UML画图工具

    刚接触UML时间不长,看了N多教学视频,下载好了几个软件各种不习惯 当我遇见了ProcessOn  从此我彻底“爱上”了它! http://www.processon.com/ UML各类例图它几乎全 ...

  6. Rabbit MQ 入门指南

    rabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统.他遵循Mozilla Public License开源协议.采用 Erlang 实现的工业级的消息队列(MQ)服务器. Ra ...

  7. 初识Identity并添加身份验证管理页面

    目录 初识Identity并添加身份验证管理页面 前言 什么是ASP.NET Core Identity 创建带有身份验证的WebApp 尝试运行 检查解决方案中的项目文件 发现问题 原因 解决问题 ...

  8. winform最小化后重复进load事件原因

    最近编写一个工具发现的问题,窗体不论是最小化还是进入托盘,重新打开的时候都会进入控件load事件. 产生这个现象的条件是: 1.使用了用户控件,在控件中使用了load事件 2.在主窗体中,隐藏或显示任 ...

  9. [leetcode.com]算法题目 - Sort Colors

    Given an array with n objects colored red, white or blue, sort them so that objects of the same colo ...

  10. SAP接口的调用

    最近做一个专案用到的SAO接口的调用,用到的上传参数获取回传的IRfcTable,以及以IRfcTable作为参数上传SAP,通过查阅很多资料,发现资料说明的也多是鱼龙混杂,许多没有实现就直接贴在上面 ...