两个问题
1.jQuery的链式操作是如何实现的?
2.为什么要用链式操作?
大家认为这两个问题哪个好回答一点呢?
链式操作
原理相信百度一下一大把,实际上链式操作仅仅是通过对象上的方法最后
return this
把对象再返回回来,对象当然可以继续调用方法啦,所以就可以链式操作了。那么,简单实现一个:
//定义一个JS类 function Demo() { } //扩展它的prototype Demo.prototype ={ setName:function (name) { this.name = name; return this; }, getName:function () { return this.name; }, setAge:function (age) { this.age = age; return this; } }; ////工厂函数 function D() { return new Demo(); } //去实现可链式的调用 D().setName("CJ").setAge(18).setName();
但……为什么要用呢?
一般的解释:
节省代码量,代码看起来更优雅。
例如如果没有链式,那么你可能需要这样写代码:
document.getElementById("ele").dosomething();
document.getElementById("ele").dootherthing();
这个代码中调用了两次document.getElementById来获取DOM树的元素,这样消耗比较大,而且要写两行,而链式只要写一行,节省了代码……
但我们也可以用缓存元素啊。比如:
var ele = document.getElementById("ele"); ele.dosomething(); ele.dootherthing();
而且两行并没有比一行多多少代码,甚至相应的封装反而使得代码更多了。
最糟糕的是所有对象的方法返回的都是对象本身,也就是说没有返回值,这不一定在任何环境下都适合。
举个例子,我们想弄一个超大整数BigInteger(意思是如果用Javascript的Number保存可能会溢出的整数),顺便扩展他的运算方法,会适合用链式操作么?
例如运算31415926535 * 4 - 271828182,如果设计成链式风格的方法可能会是这样的:
var result = (new BigInteger("31415926535")).multiply(new BigInteger("4")).subtract(new BigInteger("271828182")).val(); console.log("result == " + result);
这看起来似乎也很优雅,但是如果我们想要中间的结果怎么办呢?或许会写成这样:
var bigInteger = new BigInteger("31415926535"); var result1 = bigInteger.multiply(new BigInteger("4")).val(); var result2 = bigInteger.subtract(new BigInteger("271828182")).val(); console.log("result1 == " + result1 + ", result2 == " + result2);
这似乎一点也不优雅了,和不用链式操作没啥不同嘛!
那么如果要求是原来的BigInteger不能改变呢?好吧,链式操作似乎不能满足这个需求了。
jQuery专注于DOM对象操作,而DOM的操作会在页面上体现,不需要在Javascript中通过返回值来表示,但计算操作却不一样,我们很可能需要通过Javascript返回中间过程值另作他用。
在设计的时候,我们需要考虑链式带来的好处和坏处,因为别人用了链式,所以就用链式,可能并不是一个很好的方案。
那么到底为什么要用链式操作呢?
为了更好的异步体验
Javascript是无阻塞语言,所以他不是没阻塞,而是不能阻塞,所以他需要通过事件来驱动,异步来完成一些本需要阻塞进程的操作。
但是异步编程是一种令人疯狂的东西……运行时候是分离的倒不要紧,但是编写代码时候也是分离的就……
常见的异步编程模型有哪些呢?
- 回调函数
所谓的回调函数,意指先在系统的某个地方对函数进行注册,让系统知道这个函数的存在,然后在以后,当某个事件发生时,再调用这个函数对事件进行响应。
function f(num, callback){ if(num<0) { alert("调用低层函数处理!"); alert("分数不能为负,输入错误!"); }else if(num==0){ alert("调用低层函数处理!"); alert("该学生可能未参加考试!"); }else{ alert("调用高层函数处理!"); setTimeout(function(){callback();}, 1000); } }
这里callback则是回调函数。可以发现只有当num为非负数时候callback才会调用。
但是问题,如果我们不看函数内部,我们并不知道callback会几时调用,在什么情况下调用,代码间产生了一定耦合,流程上也会产生一定的混乱。
虽然回调函数是一种简单而易于部署的实现异步的方法,但从编程体验来说它却不够好。
- 事件监听
也就是采用事件驱动,执行顺序取决于事件顺序。
function EventTarget(){ this.handlers = {}; } EventTarget.prototype = { constructor: EventTarget, addHandler: function(type, handler){ this.handlers[type] = []; }, fire: function(){ if(!event.target){ event.target = this; } if(this.handlers[event.type instanceof Array]){ var handlers = this.handlers[event.type]; for(var i = 0, len = handlers.length, i < len; i++){ handlers[i](event); } } }, removeHandler: function(type, handler){ if(this.handlers[type] instanceof Array){ var handlers = this.handlers[type]; for(var i = 0, le = handlers.length; i < len; i++){ if(handlers[i] === handler){ break; } } handlers.splice(i, 1); } } };
上面是《JavaScript高级程序设计》中的自定义事件实现。于是我们就可以通过addHandler来绑定事件处理函数,用fire来触发事件,用removeHandler来删除事件处理函数。
虽然通过事件解耦了,但流程顺序更加混乱了。
- 链式异步
个人觉得链式操作最值得称赞的还是其解决了异步编程模型的执行流程不清晰的问题。jQuery中$(document).ready就非常好的阐释了这一理念。DOMCotentLoaded是一个事件,在DOM并未加载前,jQuery的大部分操作都不会奏效,但jQuery的设计者并没有把他当成事件一样来处理,而是转成一种“选其对象,对其操作”的思路。$选择了document对象,ready是其方法进行操作。这样子流程问题就非常清晰了,在链条越后位置的方法就越后执行。
(function(){ var isReady=false; //判断onDOMReady方法是否已经被执行过 var readyList= [];//把需要执行的方法先暂存在这个数组里 var timer;//定时器句柄 ready=function(fn) { if (isReady ) fn.call( document); else readyList.push( function() { return fn.call(this);}); return this; } var onDOMReady=function(){ for(var i=0;i<readyList.length;i++){ readyList[i].apply(document); } readyList = null; } var bindReady = function(evt){ if(isReady) return; isReady=true; onDOMReady.call(window); if(document.removeEventListener){ document.removeEventListener("DOMContentLoaded", bindReady, false); }else if(document.attachEvent){ document.detachEvent("onreadystatechange", bindReady); if(window == window.top){ clearInterval(timer); timer = null; } } }; if(document.addEventListener){ document.addEventListener("DOMContentLoaded", bindReady, false); }else if(document.attachEvent){ document.attachEvent("onreadystatechange", function(){ if((/loaded|complete/).test(document.readyState)) bindReady(); }); if(window == window.top){ timer = setInterval(function(){ try{ isReady||document.documentElement.doScroll('left');//在IE下用能否执行doScroll判断dom是否加载完毕 }catch(e){ return; } bindReady(); },5); } } })();
上面的代码不能用$(document).ready,而应该是window.ready。
- Deferred & Promise
CommonJS中的异步编程模型也延续了这一想法,
每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。
所以我们可以这样写:
f1().then(f2).then(f3);
这种方法我们无需太过关注实现,也不太需要理解异步,只要懂得通过函数选对象,通过then进行操作,就能进行异步编程。
相关推荐
jQuery的链式操作是如何实现的?为什么要用链式操作?接下来会帮助大家解决这两个问题,感兴趣的朋友可以了解下
主要介绍了jQuery链式操作,实例分析了jQuery基于链式操作动态改变页面元素样式的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
jQuery实现方法的链式操作是非常容易的。这里给出正确的使用方法
本文实例讲述了jQuery对象的链式操作用法。分享给大家供大家参考,具体如下: jQuery对象的链式操作 首先来看一个例子: 复制代码 代码如下:$(“#myphoto”).css(“border”,”solid 2px#FF0000″).attr(“alt”,” ...
主要介绍了JQuery特殊效果和链式调用操作,结合实例形式分析总结了jQuery各种常见显示效果与所使用的函数,以及链式调用显示层级菜单功能相关操作技巧,需要的朋友可以参考下
好了开始我的Jquery第一天。...jquery 链式操作</title> [removed][removed] [removed] $(document).ready(function(){ alert(“hello word!”); //静止右键点击 // $(document).bind(“contextmenu”,fu
首先,之前文章中的jquery链式操作就是jquery性能优化方式中的一种,具体实现及优势在这里就不重复了哈。其次,jquery的优化与web优化中的某些方法是一样的。 a.压缩js。使用代码压缩技术,减小文件体积。(使用...
但是这链式操作的方式实在吸引人(貌似现在不少新库都采用了链式操作)。 新手无畏嘛,所以写了以下代码。主要是避免以后又忘了,呵呵。 代码如下: window.k = function() { return new k.fn.init(arguments); } k....
主要介绍了jquery简单实现图片切换效果的方法,涉及jQuery链式操作及图片操作的相关技巧,需要的朋友可以参考下
主要介绍了jQuery判断一个元素是否可见的方法,涉及jQuery链式操作及样式判定的技巧,需要的朋友可以参考下
什么是链式操作呢?使用jQuery的同学印象应该会很深刻.在jQuery中,我们经常会这样的来操作DOM元素: $("p").css("color").addClass("selected"); 连贯操作看起来的确很酷,也非常的方便代码的阅读.那么在PHP里面是否...
主要介绍了jquery实现鼠标点击后展开列表内容的导航栏效果,通过简单的jQuery链式操作实现针对页面元素的遍历及样式动态变换功能,需要的朋友可以参考下
针对已有的小程序原生API进行简单二次封装,支持更多对原生API的简洁调用方式及链式调用方式。 托管小程序页面JS处理主函数逻辑,提高代码可读性及可维护性。 规范小程序页面数据字段类型,提高页面逻辑管理效率。 ...
主要介绍了jQuery实现鼠标滑向当前图片高亮显示并且其它图片变灰的方法,涉及jquery链式操作及页面元素样式控制的相关技巧,需要的朋友可以参考下
主要介绍了jQuery简单tab切换效果实现方法,涉及jQuery链式操作及遍历的技巧,是非常具有实用价值的功能,需要的朋友可以参考下