这一章要实现的就是jQuery的那种链式调用,例子:

  1. $(this).setStyle('color', 'green').show();
一:调用链的结构
首先我们来看一下最简单的$()函数的实现:
  1. function $() {
  2. var elements = [];
  3. for (var i = , 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 == ) {
  9. return element;
  10. }
  11. elements.push(element);
  12. }
  13. return elements;
  14. }
如果我们要实现$().method()这样的使用方法,想到应该就是$()函数有返回值,并且返回的是一个对象。要实现前面的所说的,最好的方法就是$()里面应该有个类可以让我们new一个对象出来,所以上面的代码就变成下面的样子:
  1. (function() {
  2. // Use a private class.
  3. function _$(els) {
  4. this.elements = [];
  5. for (var i = , len = els.length; i < len; ++i) {
  6. var element = els[i];
  7. if (typeof element == 'string') {
  8. element = document.getElementById(element);
  9. }
  10. this.elements.push(element);
  11. }
  12. }
  13. // The public interface remains the same.
  14. window.$ = function() {
  15. return new _$(arguments);
  16. };
  17. })();
此外我们的对象应该要有方法可以调用啊,那就定义在prototype上吧,然后代码就变成下面那样了:
  1. (function() {
  2. function _$(els) {
  3. // ...
  4. }
  5. _$.prototype = {
  6. each: function(fn) {
  7. for ( var i = , len = this.elements.length; i < len; ++i ) {
  8. fn.call(this, this.elements[i]);
  9. }
  10. return this;
  11. },
  12. setStyle: function(prop, val) {
  13. this.each(function(el) {
  14. el.style[prop] = val;
  15. });
  16. return this;
  17. },
  18. show: function() {
  19. var that = this;
  20. this.each(function(el) {
  21. that.setStyle('display', 'block');
  22. });
  23. return this;
  24. },
  25. addEvent: function(type, fn) {
  26. var add = function(el) {
  27. if (window.addEventListener) {
  28. el.addEventListener(type, fn, false);
  29. }
  30. else if (window.attachEvent) {
  31. el.attachEvent('on'+type, fn);
  32. }
  33. };
  34. this.each(function(el) {
  35. add(el);
  36. });
  37. return this;
  38. }
  39. };
  40. window.$ = function() {
  41. return new _$(arguments);
  42. };
  43. })();
到这里,我们就可以大概的使用一下了:
  1. $('test-1', 'test-2').show().
  2. setStyle('color', 'red').
  3. addEvent('click', function(e) {
  4. $(this).setStyle('color', 'green');
  5. });
二:设计一个支持方法链式调用的JavaScript库
一般的js库里面都包含着事件、DOM、Ajax这几个重要的模块,那模仿一下:
  1. Function.prototype.method = function(name, fn) {
  2. this.prototype[name] = fn;
  3. return this;
  4. };
  5. (function() {
  6. function _$(els) {
  7. // ...
  8. }
  9. /* Events * addEvent * getEvent */
  10. _$.method('addEvent', function(type, fn) {
  11. // ...
  12. }).method('getEvent', function(e) {
  13. // ...
  14. }).
  15. /* DOM * addClass * removeClass * replaceClass * hasClass * getStyle * setStyle */
  16. method('addClass', function(className) {
  17. // ...
  18. }).method('removeClass', function(className) {
  19. // ...
  20. }).method('replaceClass', function(oldClass, newClass) {
  21. // ...
  22. }).method('hasClass', function(className) {
  23. // ...
  24. }).method('getStyle', function(prop) {
  25. // ...
  26. }).method('setStyle', function(prop, val) {
  27. // ...
  28. }).
  29. /* AJAX * load. Fetches an HTML fragment from a URL and inserts it into an element. */
  30. method('load', function(uri, method) {
  31. // ...
  32. });
  33. window.$ = function() {
  34. return new _$(arguments);
  35. });
  36. })();
其实用的还是上面的方法。
不过,注意到最上面的几行代码了吗,我记得第一章说过,这样的话让添加prototype方法也使用链式调用玩起来了。。
还有,倒数第四行那里,我们总是把函数赋予给window.$,这样的话与一些使用$做命名空间的库是有冲突的,例如和jQuery有冲突~,那换命名空间吧,下面就实现一个安装器来方便改变命名空间:
  1. Function.prototype.method = function(name, fn) {
  2. // ...
  3. };
  4. (function() {
  5. function _$(els) {
  6. // ...
  7. }
  8. _$.method('addEvent', function(type, fn) {
  9. // ...
  10. })
  11. // ...
  12.  
  13. window.installHelper = function(scope, interface) {
  14. scope[interface] = function() {
  15. return new _$(arguments);
  16. }
  17. };
  18. })();
上面代码的主要思想就是先不给任何全局变量赋值,只有调用installHelper绑定相应的命名空间之后才能使用。
使用方法如下:
  1. installHelper(window, '$');
  2.  
  3. $('example').show();
这样就等于把函数赋值给了window.$了。
三:使用回调从支持链式调用的方法获取数据
上面说的那些链式方法都是返回this的,如果方法本身要返回值了?那么和返回this不就冲突了吗?所以对于这种情况,我们要想出一种方法,那就是对于这种情况,我们传入一个回调函数,来调用返回来的数值,之后还是要返回this的~
例子:
  1. window.API2 = window.API2 || {};
  2. API2.prototype = function() {
  3. var name = 'Hello world';
  4. // Privileged mutator method.
  5. setName: function(newName) {
  6. name = newName;
  7. return this;
  8. },
  9. // Privileged accessor method.
  10. getName: function(callback) {
  11. callback.call(this, name);
  12. return this;
  13. }
  14. }();
上面代码只要看getName哪里就可以了,传入了一个回调函数,然后取出值来直接调用,之后还是返回this,就不破坏链式调用了。
上面代码的一个使用方法:
  1. var o2 = new API2;
  2. o2.getName(console.log).setName('Meow').getName(console.log);
 

《javascript设计模式》笔记之第六章:方法的链式调用的更多相关文章

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

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

  2. 如何写 JS 的链式调用 ---》JS 设计模式《----方法的链式调用

    1.以$ 函数为例.通常返回一个HTML元素或一个元素集合. 代码如下: function $(){ var elements = []; ;i<arguments.length;i++){ v ...

  3. js实现方法的链式调用

    假如这里有三个方法:person.unmerried();person.process();person.married();在jQuery中通常的写法是:person.unmerried().pro ...

  4. PHP 设计模式 笔记与总结(4)PHP 链式操作的实现

    PHP 链式操作的实现 $db->where()->limit()->order(); 在 Common 下创建 Database.php. 链式操作最核心的地方在于:在方法的最后 ...

  5. JS设计模式——6.方法的链式调用

    什么是链式调用 这个很容易理解,例如: $(this).setStyle('color', 'red').show(); 分解链式调用 链式调用其实是两个部分: 1.操作对象(也就是被操作的DOM元素 ...

  6. Javascript设计模式笔记

    Javascript是越来越厉害了,一统前后端开发.于是最近把设计模式又看了一遍,顺便做了个笔记,以方便自己和他人共同学习. 笔记连载详见:http://www.meteorcn.net/wordpr ...

  7. 浅析 JavaScript 链式调用

    对$函数你已经很熟悉了.它通常返回一个html元素或一个html元素的集合,如下: function$(){ var elements = []; for(vari=0,len=arguments.l ...

  8. 《HTTP 权威指南》笔记:第十六章&第十七章 国际化、内容协商与转码

    <HTTP 权威指南>笔记:第十六章 国际化 客户端通过在请求报文中的 Accept-Language 首部和 Accept-Charset 首部来告知服务器:“我理解这些语言.”服务器通 ...

  9. [书籍翻译] 《JavaScript并发编程》第六章 实用的并发

    本文是我翻译<JavaScript Concurrency>书籍的第六章 实用的并发,该书主要以Promises.Generator.Web workers等技术来讲解JavaScript ...

随机推荐

  1. js日期和时间戳互换

    <script> function js_strto_time(str_time){ var new_str = str_time.replace(/:/g,'-'); new_str = ...

  2. oracle 左右链接

    数据表的连接有: 1.内连接(自然连接): inner只有两个表相匹配的行才能在结果集中出现 2.外连接: 包括 (1)左外连接(左边的表不加限制) (2)右外连接(右边的表不加限制) (3)全外连接 ...

  3. 「LOJ#103」子串查找 (Hash

    题目描述 这是一道模板题. 给定一个字符串 A A A 和一个字符串 B B B,求 B B B 在 A A A 中的出现次数.AAA 和 BBB 中的字符均为英语大写字母或小写字母. A A A 中 ...

  4. Field 'CID' doesn't have a default value

    解决:在数据库客户端navicat中设计表勾选自动递增

  5. 前端调用后端接口返回200(成功状态码),后端有返回,但是控制台Network Response为空,没展示任何信息

    解决方法: 1.在js里面debugger,可以看到后台是否有返回数据. 2.直接console.log(),直接把返回值打印出来,查看返回的数据格式,方便前端进行数据的处理. PS:因为后端返回的数 ...

  6. Mutual information and Normalized Mutual information 互信息和标准化互信息

    实验室最近用到nmi( Normalized Mutual information )评价聚类效果,在网上找了一下这个算法的实现,发现满意的不多. 浙江大学蔡登教授有一个,http://www.zju ...

  7. sip协议呼叫流程详解

    1.SIP业务基本知识 1.1 业务介绍会话初始协议(Session Initiation Protocol)是一种信令协议,用于初始.管理和终止网络中的语音和视频会话,具体地说就是用来生成.修改和终 ...

  8. 【转】cache buffer chain 第一篇

    文章转自:http://www.jydba.net/cache-buffer-chain/ buffer cache的管理有两个重要的数据结构: hash bucket和cache buffer ch ...

  9. 使用IntelliJ IDEA配置Tomcat(入门)

    一.下载Tomcat 1.进入官网http://tomcat.apache.org/,选择download,下载所需Tomcat版本. 此处我们选择下载最新版本Tomcat 9. 注意有zip和exe ...

  10. 反射invoke()方法

    invoke()方法: 主要是为了类反射,可以在不知道具体类的情况下,根据配置字符串去调用一个类的方法.最简单的方法是可以把方法参数化.    main.invoke():     比如Test类里有 ...